0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/backlight.h>
0009 #include <linux/delay.h>
0010 #include <linux/err.h>
0011 #include <linux/gpio/consumer.h>
0012 #include <linux/i2c.h>
0013 #include <linux/module.h>
0014 #include <linux/of.h>
0015 #include <linux/of_device.h>
0016 #include <linux/pm.h>
0017 #include <linux/regulator/consumer.h>
0018
0019 #include <drm/drm_atomic_helper.h>
0020 #include <drm/drm_bridge.h>
0021 #include <drm/drm_crtc.h>
0022 #include <drm/drm_of.h>
0023 #include <drm/drm_panel.h>
0024 #include <drm/drm_print.h>
0025 #include <drm/drm_probe_helper.h>
0026
0027
0028 #define PS8622_MAX_BRIGHTNESS 0xff
0029
0030
0031 #define PS8622_POWER_RISE_T1_MIN_US 10
0032 #define PS8622_POWER_RISE_T1_MAX_US 10000
0033 #define PS8622_RST_HIGH_T2_MIN_US 3000
0034 #define PS8622_RST_HIGH_T2_MAX_US 30000
0035 #define PS8622_PWMO_END_T12_MS 200
0036 #define PS8622_POWER_FALL_T16_MAX_US 10000
0037 #define PS8622_POWER_OFF_T17_MS 500
0038
0039 #if ((PS8622_RST_HIGH_T2_MIN_US + PS8622_POWER_RISE_T1_MAX_US) > \
0040 (PS8622_RST_HIGH_T2_MAX_US + PS8622_POWER_RISE_T1_MIN_US))
0041 #error "T2.min + T1.max must be less than T2.max + T1.min"
0042 #endif
0043
0044 struct ps8622_bridge {
0045 struct i2c_client *client;
0046 struct drm_bridge bridge;
0047 struct drm_bridge *panel_bridge;
0048 struct regulator *v12;
0049 struct backlight_device *bl;
0050
0051 struct gpio_desc *gpio_slp;
0052 struct gpio_desc *gpio_rst;
0053
0054 u32 max_lane_count;
0055 u32 lane_count;
0056
0057 bool enabled;
0058 };
0059
0060 static inline struct ps8622_bridge *
0061 bridge_to_ps8622(struct drm_bridge *bridge)
0062 {
0063 return container_of(bridge, struct ps8622_bridge, bridge);
0064 }
0065
0066 static int ps8622_set(struct i2c_client *client, u8 page, u8 reg, u8 val)
0067 {
0068 int ret;
0069 struct i2c_adapter *adap = client->adapter;
0070 struct i2c_msg msg;
0071 u8 data[] = {reg, val};
0072
0073 msg.addr = client->addr + page;
0074 msg.flags = 0;
0075 msg.len = sizeof(data);
0076 msg.buf = data;
0077
0078 ret = i2c_transfer(adap, &msg, 1);
0079 if (ret != 1)
0080 pr_warn("PS8622 I2C write (0x%02x,0x%02x,0x%02x) failed: %d\n",
0081 client->addr + page, reg, val, ret);
0082 return !(ret == 1);
0083 }
0084
0085 static int ps8622_send_config(struct ps8622_bridge *ps8622)
0086 {
0087 struct i2c_client *cl = ps8622->client;
0088 int err = 0;
0089
0090
0091 err = ps8622_set(cl, 0x02, 0xa1, 0x01);
0092 if (err)
0093 goto error;
0094
0095
0096 err = ps8622_set(cl, 0x04, 0x14, 0x01);
0097 if (err)
0098 goto error;
0099
0100
0101 err = ps8622_set(cl, 0x04, 0xe3, 0x20);
0102 if (err)
0103 goto error;
0104
0105
0106 err = ps8622_set(cl, 0x04, 0xe2, 0x80);
0107 if (err)
0108 goto error;
0109
0110
0111
0112
0113
0114 err = ps8622_set(cl, 0x04, 0x8a, 0x0c);
0115 if (err)
0116 goto error;
0117
0118
0119 err = ps8622_set(cl, 0x04, 0x89, 0x08);
0120 if (err)
0121 goto error;
0122
0123
0124 err = ps8622_set(cl, 0x04, 0x71, 0x2d);
0125 if (err)
0126 goto error;
0127
0128
0129 err = ps8622_set(cl, 0x04, 0x7d, 0x07);
0130 if (err)
0131 goto error;
0132
0133
0134 err = ps8622_set(cl, 0x04, 0x7b, 0x00);
0135 if (err)
0136 goto error;
0137
0138
0139 err = ps8622_set(cl, 0x04, 0x7a, 0xfd);
0140 if (err)
0141 goto error;
0142
0143
0144 err = ps8622_set(cl, 0x04, 0xc0, 0x12);
0145 if (err)
0146 goto error;
0147
0148
0149 err = ps8622_set(cl, 0x04, 0xc1, 0x92);
0150 if (err)
0151 goto error;
0152
0153
0154 err = ps8622_set(cl, 0x04, 0xc2, 0x1c);
0155 if (err)
0156 goto error;
0157
0158
0159 err = ps8622_set(cl, 0x04, 0x32, 0x80);
0160 if (err)
0161 goto error;
0162
0163
0164 err = ps8622_set(cl, 0x04, 0x00, 0xb0);
0165 if (err)
0166 goto error;
0167
0168
0169 err = ps8622_set(cl, 0x04, 0x15, 0x40);
0170 if (err)
0171 goto error;
0172
0173
0174 err = ps8622_set(cl, 0x04, 0x54, 0x10);
0175 if (err)
0176 goto error;
0177
0178
0179
0180 err = ps8622_set(cl, 0x01, 0x02, 0x80 | ps8622->max_lane_count);
0181 if (err)
0182 goto error;
0183
0184
0185 err = ps8622_set(cl, 0x01, 0x21, 0x80 | ps8622->lane_count);
0186 if (err)
0187 goto error;
0188
0189 err = ps8622_set(cl, 0x00, 0x52, 0x20);
0190 if (err)
0191 goto error;
0192
0193
0194 err = ps8622_set(cl, 0x00, 0xf1, 0x03);
0195 if (err)
0196 goto error;
0197
0198 err = ps8622_set(cl, 0x00, 0x62, 0x41);
0199 if (err)
0200 goto error;
0201
0202
0203 err = ps8622_set(cl, 0x00, 0xf6, 0x01);
0204 if (err)
0205 goto error;
0206
0207
0208 err = ps8622_set(cl, 0x00, 0x77, 0x06);
0209 if (err)
0210 goto error;
0211
0212
0213 err = ps8622_set(cl, 0x00, 0x4c, 0x04);
0214 if (err)
0215 goto error;
0216
0217
0218 err = ps8622_set(cl, 0x01, 0xc0, 0x00);
0219 if (err)
0220 goto error;
0221
0222
0223 err = ps8622_set(cl, 0x01, 0xc1, 0x1c);
0224 if (err)
0225 goto error;
0226
0227
0228 err = ps8622_set(cl, 0x01, 0xc2, 0xf8);
0229 if (err)
0230 goto error;
0231
0232
0233 err = ps8622_set(cl, 0x01, 0xc3, 0x44);
0234 if (err)
0235 goto error;
0236
0237
0238 err = ps8622_set(cl, 0x01, 0xc4, 0x32);
0239 if (err)
0240 goto error;
0241
0242
0243 err = ps8622_set(cl, 0x01, 0xc5, 0x53);
0244 if (err)
0245 goto error;
0246
0247
0248 err = ps8622_set(cl, 0x01, 0xc6, 0x4c);
0249 if (err)
0250 goto error;
0251
0252
0253 err = ps8622_set(cl, 0x01, 0xc7, 0x56);
0254 if (err)
0255 goto error;
0256
0257
0258 err = ps8622_set(cl, 0x01, 0xc8, 0x35);
0259 if (err)
0260 goto error;
0261
0262
0263 err = ps8622_set(cl, 0x01, 0xca, 0x01);
0264 if (err)
0265 goto error;
0266
0267
0268 err = ps8622_set(cl, 0x01, 0xcb, 0x05);
0269 if (err)
0270 goto error;
0271
0272
0273 if (ps8622->bl) {
0274
0275 err = ps8622_set(cl, 0x01, 0xa5, 0xa0);
0276 if (err)
0277 goto error;
0278
0279
0280 err = ps8622_set(cl, 0x01, 0xa7,
0281 ps8622->bl->props.brightness);
0282 if (err)
0283 goto error;
0284 } else {
0285
0286 err = ps8622_set(cl, 0x01, 0xa5, 0x80);
0287 if (err)
0288 goto error;
0289 }
0290
0291
0292 err = ps8622_set(cl, 0x01, 0xcc, 0x13);
0293 if (err)
0294 goto error;
0295
0296
0297 err = ps8622_set(cl, 0x02, 0xb1, 0x20);
0298 if (err)
0299 goto error;
0300
0301
0302 err = ps8622_set(cl, 0x04, 0x10, 0x16);
0303 if (err)
0304 goto error;
0305
0306
0307
0308 err = ps8622_set(cl, 0x04, 0x59, 0x60);
0309 if (err)
0310 goto error;
0311
0312
0313 err = ps8622_set(cl, 0x04, 0x54, 0x14);
0314 if (err)
0315 goto error;
0316
0317
0318 err = ps8622_set(cl, 0x02, 0xa1, 0x91);
0319
0320 error:
0321 return err ? -EIO : 0;
0322 }
0323
0324 static int ps8622_backlight_update(struct backlight_device *bl)
0325 {
0326 struct ps8622_bridge *ps8622 = dev_get_drvdata(&bl->dev);
0327 int ret, brightness = backlight_get_brightness(bl);
0328
0329 if (!ps8622->enabled)
0330 return -EINVAL;
0331
0332 ret = ps8622_set(ps8622->client, 0x01, 0xa7, brightness);
0333
0334 return ret;
0335 }
0336
0337 static const struct backlight_ops ps8622_backlight_ops = {
0338 .update_status = ps8622_backlight_update,
0339 };
0340
0341 static void ps8622_pre_enable(struct drm_bridge *bridge)
0342 {
0343 struct ps8622_bridge *ps8622 = bridge_to_ps8622(bridge);
0344 int ret;
0345
0346 if (ps8622->enabled)
0347 return;
0348
0349 gpiod_set_value(ps8622->gpio_rst, 0);
0350
0351 if (ps8622->v12) {
0352 ret = regulator_enable(ps8622->v12);
0353 if (ret)
0354 DRM_ERROR("fails to enable ps8622->v12");
0355 }
0356
0357 gpiod_set_value(ps8622->gpio_slp, 1);
0358
0359
0360
0361
0362
0363
0364
0365
0366
0367
0368
0369 usleep_range(PS8622_RST_HIGH_T2_MIN_US + PS8622_POWER_RISE_T1_MAX_US,
0370 PS8622_RST_HIGH_T2_MAX_US + PS8622_POWER_RISE_T1_MIN_US);
0371
0372 gpiod_set_value(ps8622->gpio_rst, 1);
0373
0374
0375 usleep_range(20000, 30000);
0376
0377 ret = ps8622_send_config(ps8622);
0378 if (ret) {
0379 DRM_ERROR("Failed to send config to bridge (%d)\n", ret);
0380 return;
0381 }
0382
0383 ps8622->enabled = true;
0384 }
0385
0386 static void ps8622_disable(struct drm_bridge *bridge)
0387 {
0388
0389 msleep(PS8622_PWMO_END_T12_MS);
0390 }
0391
0392 static void ps8622_post_disable(struct drm_bridge *bridge)
0393 {
0394 struct ps8622_bridge *ps8622 = bridge_to_ps8622(bridge);
0395
0396 if (!ps8622->enabled)
0397 return;
0398
0399 ps8622->enabled = false;
0400
0401
0402
0403
0404
0405
0406 gpiod_set_value(ps8622->gpio_slp, 0);
0407
0408 if (ps8622->v12)
0409 regulator_disable(ps8622->v12);
0410
0411
0412
0413
0414
0415 usleep_range(PS8622_POWER_FALL_T16_MAX_US,
0416 2 * PS8622_POWER_FALL_T16_MAX_US);
0417 gpiod_set_value(ps8622->gpio_rst, 0);
0418
0419 msleep(PS8622_POWER_OFF_T17_MS);
0420 }
0421
0422 static int ps8622_attach(struct drm_bridge *bridge,
0423 enum drm_bridge_attach_flags flags)
0424 {
0425 struct ps8622_bridge *ps8622 = bridge_to_ps8622(bridge);
0426
0427 return drm_bridge_attach(ps8622->bridge.encoder, ps8622->panel_bridge,
0428 &ps8622->bridge, flags);
0429 }
0430
0431 static const struct drm_bridge_funcs ps8622_bridge_funcs = {
0432 .pre_enable = ps8622_pre_enable,
0433 .disable = ps8622_disable,
0434 .post_disable = ps8622_post_disable,
0435 .attach = ps8622_attach,
0436 };
0437
0438 static const struct of_device_id ps8622_devices[] = {
0439 {.compatible = "parade,ps8622",},
0440 {.compatible = "parade,ps8625",},
0441 {}
0442 };
0443 MODULE_DEVICE_TABLE(of, ps8622_devices);
0444
0445 static int ps8622_probe(struct i2c_client *client,
0446 const struct i2c_device_id *id)
0447 {
0448 struct device *dev = &client->dev;
0449 struct ps8622_bridge *ps8622;
0450 struct drm_bridge *panel_bridge;
0451 int ret;
0452
0453 ps8622 = devm_kzalloc(dev, sizeof(*ps8622), GFP_KERNEL);
0454 if (!ps8622)
0455 return -ENOMEM;
0456
0457 panel_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0, 0);
0458 if (IS_ERR(panel_bridge))
0459 return PTR_ERR(panel_bridge);
0460
0461 ps8622->panel_bridge = panel_bridge;
0462 ps8622->client = client;
0463
0464 ps8622->v12 = devm_regulator_get(dev, "vdd12");
0465 if (IS_ERR(ps8622->v12)) {
0466 dev_info(dev, "no 1.2v regulator found for PS8622\n");
0467 ps8622->v12 = NULL;
0468 }
0469
0470 ps8622->gpio_slp = devm_gpiod_get(dev, "sleep", GPIOD_OUT_HIGH);
0471 if (IS_ERR(ps8622->gpio_slp)) {
0472 ret = PTR_ERR(ps8622->gpio_slp);
0473 dev_err(dev, "cannot get gpio_slp %d\n", ret);
0474 return ret;
0475 }
0476
0477
0478
0479
0480
0481 ps8622->gpio_rst = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
0482 if (IS_ERR(ps8622->gpio_rst)) {
0483 ret = PTR_ERR(ps8622->gpio_rst);
0484 dev_err(dev, "cannot get gpio_rst %d\n", ret);
0485 return ret;
0486 }
0487
0488 ps8622->max_lane_count = id->driver_data;
0489
0490 if (of_property_read_u32(dev->of_node, "lane-count",
0491 &ps8622->lane_count)) {
0492 ps8622->lane_count = ps8622->max_lane_count;
0493 } else if (ps8622->lane_count > ps8622->max_lane_count) {
0494 dev_info(dev, "lane-count property is too high,"
0495 "using max_lane_count\n");
0496 ps8622->lane_count = ps8622->max_lane_count;
0497 }
0498
0499 if (!of_find_property(dev->of_node, "use-external-pwm", NULL)) {
0500 ps8622->bl = backlight_device_register("ps8622-backlight",
0501 dev, ps8622, &ps8622_backlight_ops,
0502 NULL);
0503 if (IS_ERR(ps8622->bl)) {
0504 DRM_ERROR("failed to register backlight\n");
0505 ret = PTR_ERR(ps8622->bl);
0506 ps8622->bl = NULL;
0507 return ret;
0508 }
0509 ps8622->bl->props.max_brightness = PS8622_MAX_BRIGHTNESS;
0510 ps8622->bl->props.brightness = PS8622_MAX_BRIGHTNESS;
0511 }
0512
0513 ps8622->bridge.funcs = &ps8622_bridge_funcs;
0514 ps8622->bridge.type = DRM_MODE_CONNECTOR_LVDS;
0515 ps8622->bridge.of_node = dev->of_node;
0516 drm_bridge_add(&ps8622->bridge);
0517
0518 i2c_set_clientdata(client, ps8622);
0519
0520 return 0;
0521 }
0522
0523 static int ps8622_remove(struct i2c_client *client)
0524 {
0525 struct ps8622_bridge *ps8622 = i2c_get_clientdata(client);
0526
0527 backlight_device_unregister(ps8622->bl);
0528 drm_bridge_remove(&ps8622->bridge);
0529
0530 return 0;
0531 }
0532
0533 static const struct i2c_device_id ps8622_i2c_table[] = {
0534
0535 {"ps8622", 1},
0536 {"ps8625", 2},
0537 {},
0538 };
0539 MODULE_DEVICE_TABLE(i2c, ps8622_i2c_table);
0540
0541 static struct i2c_driver ps8622_driver = {
0542 .id_table = ps8622_i2c_table,
0543 .probe = ps8622_probe,
0544 .remove = ps8622_remove,
0545 .driver = {
0546 .name = "ps8622",
0547 .of_match_table = ps8622_devices,
0548 },
0549 };
0550 module_i2c_driver(ps8622_driver);
0551
0552 MODULE_AUTHOR("Vincent Palatin <vpalatin@chromium.org>");
0553 MODULE_DESCRIPTION("Parade ps8622/ps8625 eDP-LVDS converter driver");
0554 MODULE_LICENSE("GPL v2");