620 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Chrontel CH7033 Video Encoder Driver4 *5 * Copyright (C) 2019,2020 Lubomir Rintel6 */7 8#include <linux/gpio/consumer.h>9#include <linux/i2c.h>10#include <linux/module.h>11#include <linux/regmap.h>12 13#include <drm/drm_atomic_helper.h>14#include <drm/drm_bridge.h>15#include <drm/drm_edid.h>16#include <drm/drm_of.h>17#include <drm/drm_print.h>18#include <drm/drm_probe_helper.h>19 20/* Page 0, Register 0x07 */21enum {22 DRI_PD = BIT(3),23 IO_PD = BIT(5),24};25 26/* Page 0, Register 0x08 */27enum {28 DRI_PDDRI = GENMASK(7, 4),29 PDDAC = GENMASK(3, 1),30 PANEN = BIT(0),31};32 33/* Page 0, Register 0x09 */34enum {35 DPD = BIT(7),36 GCKOFF = BIT(6),37 TV_BP = BIT(5),38 SCLPD = BIT(4),39 SDPD = BIT(3),40 VGA_PD = BIT(2),41 HDBKPD = BIT(1),42 HDMI_PD = BIT(0),43};44 45/* Page 0, Register 0x0a */46enum {47 MEMINIT = BIT(7),48 MEMIDLE = BIT(6),49 MEMPD = BIT(5),50 STOP = BIT(4),51 LVDS_PD = BIT(3),52 HD_DVIB = BIT(2),53 HDCP_PD = BIT(1),54 MCU_PD = BIT(0),55};56 57/* Page 0, Register 0x18 */58enum {59 IDF = GENMASK(7, 4),60 INTEN = BIT(3),61 SWAP = GENMASK(2, 0),62};63 64enum {65 BYTE_SWAP_RGB = 0,66 BYTE_SWAP_RBG = 1,67 BYTE_SWAP_GRB = 2,68 BYTE_SWAP_GBR = 3,69 BYTE_SWAP_BRG = 4,70 BYTE_SWAP_BGR = 5,71};72 73/* Page 0, Register 0x19 */74enum {75 HPO_I = BIT(5),76 VPO_I = BIT(4),77 DEPO_I = BIT(3),78 CRYS_EN = BIT(2),79 GCLKFREQ = GENMASK(2, 0),80};81 82/* Page 0, Register 0x2e */83enum {84 HFLIP = BIT(7),85 VFLIP = BIT(6),86 DEPO_O = BIT(5),87 HPO_O = BIT(4),88 VPO_O = BIT(3),89 TE = GENMASK(2, 0),90};91 92/* Page 0, Register 0x2b */93enum {94 SWAPS = GENMASK(7, 4),95 VFMT = GENMASK(3, 0),96};97 98/* Page 0, Register 0x54 */99enum {100 COMP_BP = BIT(7),101 DAC_EN_T = BIT(6),102 HWO_HDMI_HI = GENMASK(5, 3),103 HOO_HDMI_HI = GENMASK(2, 0),104};105 106/* Page 0, Register 0x57 */107enum {108 FLDSEN = BIT(7),109 VWO_HDMI_HI = GENMASK(5, 3),110 VOO_HDMI_HI = GENMASK(2, 0),111};112 113/* Page 0, Register 0x7e */114enum {115 HDMI_LVDS_SEL = BIT(7),116 DE_GEN = BIT(6),117 PWM_INDEX_HI = BIT(5),118 USE_DE = BIT(4),119 R_INT = GENMASK(3, 0),120};121 122/* Page 1, Register 0x07 */123enum {124 BPCKSEL = BIT(7),125 DRI_CMFB_EN = BIT(6),126 CEC_PUEN = BIT(5),127 CEC_T = BIT(3),128 CKINV = BIT(2),129 CK_TVINV = BIT(1),130 DRI_CKS2 = BIT(0),131};132 133/* Page 1, Register 0x08 */134enum {135 DACG = BIT(6),136 DACKTST = BIT(5),137 DEDGEB = BIT(4),138 SYO = BIT(3),139 DRI_IT_LVDS = GENMASK(2, 1),140 DISPON = BIT(0),141};142 143/* Page 1, Register 0x0c */144enum {145 DRI_PLL_CP = GENMASK(7, 6),146 DRI_PLL_DIVSEL = BIT(5),147 DRI_PLL_N1_1 = BIT(4),148 DRI_PLL_N1_0 = BIT(3),149 DRI_PLL_N3_1 = BIT(2),150 DRI_PLL_N3_0 = BIT(1),151 DRI_PLL_CKTSTEN = BIT(0),152};153 154/* Page 1, Register 0x6b */155enum {156 VCO3CS = GENMASK(7, 6),157 ICPGBK2_0 = GENMASK(5, 3),158 DRI_VCO357SC = BIT(2),159 PDPLL2 = BIT(1),160 DRI_PD_SER = BIT(0),161};162 163/* Page 1, Register 0x6c */164enum {165 PLL2N11 = GENMASK(7, 4),166 PLL2N5_4 = BIT(3),167 PLL2N5_TOP = BIT(2),168 DRI_PLL_PD = BIT(1),169 PD_I2CM = BIT(0),170};171 172/* Page 3, Register 0x28 */173enum {174 DIFF_EN = GENMASK(7, 6),175 CORREC_EN = GENMASK(5, 4),176 VGACLK_BP = BIT(3),177 HM_LV_SEL = BIT(2),178 HD_VGA_SEL = BIT(1),179};180 181/* Page 3, Register 0x2a */182enum {183 LVDSCLK_BP = BIT(7),184 HDTVCLK_BP = BIT(6),185 HDMICLK_BP = BIT(5),186 HDTV_BP = BIT(4),187 HDMI_BP = BIT(3),188 THRWL = GENMASK(2, 0),189};190 191/* Page 4, Register 0x52 */192enum {193 PGM_ARSTB = BIT(7),194 MCU_ARSTB = BIT(6),195 MCU_RETB = BIT(2),196 RESETIB = BIT(1),197 RESETDB = BIT(0),198};199 200struct ch7033_priv {201 struct regmap *regmap;202 struct drm_bridge *next_bridge;203 struct drm_bridge bridge;204 struct drm_connector connector;205};206 207#define conn_to_ch7033_priv(x) \208 container_of(x, struct ch7033_priv, connector)209#define bridge_to_ch7033_priv(x) \210 container_of(x, struct ch7033_priv, bridge)211 212 213static enum drm_connector_status ch7033_connector_detect(214 struct drm_connector *connector, bool force)215{216 struct ch7033_priv *priv = conn_to_ch7033_priv(connector);217 218 return drm_bridge_detect(priv->next_bridge);219}220 221static const struct drm_connector_funcs ch7033_connector_funcs = {222 .reset = drm_atomic_helper_connector_reset,223 .fill_modes = drm_helper_probe_single_connector_modes,224 .detect = ch7033_connector_detect,225 .destroy = drm_connector_cleanup,226 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,227 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,228};229 230static int ch7033_connector_get_modes(struct drm_connector *connector)231{232 struct ch7033_priv *priv = conn_to_ch7033_priv(connector);233 const struct drm_edid *drm_edid;234 int ret;235 236 drm_edid = drm_bridge_edid_read(priv->next_bridge, connector);237 drm_edid_connector_update(connector, drm_edid);238 if (drm_edid) {239 ret = drm_edid_connector_add_modes(connector);240 drm_edid_free(drm_edid);241 } else {242 ret = drm_add_modes_noedid(connector, 1920, 1080);243 drm_set_preferred_mode(connector, 1024, 768);244 }245 246 return ret;247}248 249static struct drm_encoder *ch7033_connector_best_encoder(250 struct drm_connector *connector)251{252 struct ch7033_priv *priv = conn_to_ch7033_priv(connector);253 254 return priv->bridge.encoder;255}256 257static const struct drm_connector_helper_funcs ch7033_connector_helper_funcs = {258 .get_modes = ch7033_connector_get_modes,259 .best_encoder = ch7033_connector_best_encoder,260};261 262static void ch7033_hpd_event(void *arg, enum drm_connector_status status)263{264 struct ch7033_priv *priv = arg;265 266 if (priv->bridge.dev)267 drm_helper_hpd_irq_event(priv->connector.dev);268}269 270static int ch7033_bridge_attach(struct drm_bridge *bridge,271 enum drm_bridge_attach_flags flags)272{273 struct ch7033_priv *priv = bridge_to_ch7033_priv(bridge);274 struct drm_connector *connector = &priv->connector;275 int ret;276 277 ret = drm_bridge_attach(bridge->encoder, priv->next_bridge, bridge,278 DRM_BRIDGE_ATTACH_NO_CONNECTOR);279 if (ret)280 return ret;281 282 if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)283 return 0;284 285 if (priv->next_bridge->ops & DRM_BRIDGE_OP_DETECT) {286 connector->polled = DRM_CONNECTOR_POLL_HPD;287 } else {288 connector->polled = DRM_CONNECTOR_POLL_CONNECT |289 DRM_CONNECTOR_POLL_DISCONNECT;290 }291 292 if (priv->next_bridge->ops & DRM_BRIDGE_OP_HPD) {293 drm_bridge_hpd_enable(priv->next_bridge, ch7033_hpd_event,294 priv);295 }296 297 drm_connector_helper_add(connector,298 &ch7033_connector_helper_funcs);299 ret = drm_connector_init_with_ddc(bridge->dev, &priv->connector,300 &ch7033_connector_funcs,301 priv->next_bridge->type,302 priv->next_bridge->ddc);303 if (ret) {304 DRM_ERROR("Failed to initialize connector\n");305 return ret;306 }307 308 return drm_connector_attach_encoder(&priv->connector, bridge->encoder);309}310 311static void ch7033_bridge_detach(struct drm_bridge *bridge)312{313 struct ch7033_priv *priv = bridge_to_ch7033_priv(bridge);314 315 if (priv->next_bridge->ops & DRM_BRIDGE_OP_HPD)316 drm_bridge_hpd_disable(priv->next_bridge);317 drm_connector_cleanup(&priv->connector);318}319 320static enum drm_mode_status ch7033_bridge_mode_valid(struct drm_bridge *bridge,321 const struct drm_display_info *info,322 const struct drm_display_mode *mode)323{324 if (mode->clock > 165000)325 return MODE_CLOCK_HIGH;326 if (mode->hdisplay >= 1920)327 return MODE_BAD_HVALUE;328 if (mode->vdisplay >= 1080)329 return MODE_BAD_VVALUE;330 return MODE_OK;331}332 333static void ch7033_bridge_disable(struct drm_bridge *bridge)334{335 struct ch7033_priv *priv = bridge_to_ch7033_priv(bridge);336 337 regmap_write(priv->regmap, 0x03, 0x04);338 regmap_update_bits(priv->regmap, 0x52, RESETDB, 0x00);339}340 341static void ch7033_bridge_enable(struct drm_bridge *bridge)342{343 struct ch7033_priv *priv = bridge_to_ch7033_priv(bridge);344 345 regmap_write(priv->regmap, 0x03, 0x04);346 regmap_update_bits(priv->regmap, 0x52, RESETDB, RESETDB);347}348 349static void ch7033_bridge_mode_set(struct drm_bridge *bridge,350 const struct drm_display_mode *mode,351 const struct drm_display_mode *adjusted_mode)352{353 struct ch7033_priv *priv = bridge_to_ch7033_priv(bridge);354 int hbporch = mode->hsync_start - mode->hdisplay;355 int hsynclen = mode->hsync_end - mode->hsync_start;356 int vbporch = mode->vsync_start - mode->vdisplay;357 int vsynclen = mode->vsync_end - mode->vsync_start;358 359 /*360 * Page 4361 */362 regmap_write(priv->regmap, 0x03, 0x04);363 364 /* Turn everything off to set all the registers to their defaults. */365 regmap_write(priv->regmap, 0x52, 0x00);366 /* Bring I/O block up. */367 regmap_write(priv->regmap, 0x52, RESETIB);368 369 /*370 * Page 0371 */372 regmap_write(priv->regmap, 0x03, 0x00);373 374 /* Bring up parts we need from the power down. */375 regmap_update_bits(priv->regmap, 0x07, DRI_PD | IO_PD, 0);376 regmap_update_bits(priv->regmap, 0x08, DRI_PDDRI | PDDAC | PANEN, 0);377 regmap_update_bits(priv->regmap, 0x09, DPD | GCKOFF |378 HDMI_PD | VGA_PD, 0);379 regmap_update_bits(priv->regmap, 0x0a, HD_DVIB, 0);380 381 /* Horizontal input timing. */382 regmap_write(priv->regmap, 0x0b, (mode->htotal >> 8) << 3 |383 (mode->hdisplay >> 8));384 regmap_write(priv->regmap, 0x0c, mode->hdisplay);385 regmap_write(priv->regmap, 0x0d, mode->htotal);386 regmap_write(priv->regmap, 0x0e, (hsynclen >> 8) << 3 |387 (hbporch >> 8));388 regmap_write(priv->regmap, 0x0f, hbporch);389 regmap_write(priv->regmap, 0x10, hsynclen);390 391 /* Vertical input timing. */392 regmap_write(priv->regmap, 0x11, (mode->vtotal >> 8) << 3 |393 (mode->vdisplay >> 8));394 regmap_write(priv->regmap, 0x12, mode->vdisplay);395 regmap_write(priv->regmap, 0x13, mode->vtotal);396 regmap_write(priv->regmap, 0x14, ((vsynclen >> 8) << 3) |397 (vbporch >> 8));398 regmap_write(priv->regmap, 0x15, vbporch);399 regmap_write(priv->regmap, 0x16, vsynclen);400 401 /* Input color swap. */402 regmap_update_bits(priv->regmap, 0x18, SWAP, BYTE_SWAP_BGR);403 404 /* Input clock and sync polarity. */405 regmap_update_bits(priv->regmap, 0x19, 0x1, mode->clock >> 16);406 regmap_update_bits(priv->regmap, 0x19, HPO_I | VPO_I | GCLKFREQ,407 (mode->flags & DRM_MODE_FLAG_PHSYNC) ? HPO_I : 0 |408 (mode->flags & DRM_MODE_FLAG_PVSYNC) ? VPO_I : 0 |409 mode->clock >> 16);410 regmap_write(priv->regmap, 0x1a, mode->clock >> 8);411 regmap_write(priv->regmap, 0x1b, mode->clock);412 413 /* Horizontal output timing. */414 regmap_write(priv->regmap, 0x1f, (mode->htotal >> 8) << 3 |415 (mode->hdisplay >> 8));416 regmap_write(priv->regmap, 0x20, mode->hdisplay);417 regmap_write(priv->regmap, 0x21, mode->htotal);418 419 /* Vertical output timing. */420 regmap_write(priv->regmap, 0x25, (mode->vtotal >> 8) << 3 |421 (mode->vdisplay >> 8));422 regmap_write(priv->regmap, 0x26, mode->vdisplay);423 regmap_write(priv->regmap, 0x27, mode->vtotal);424 425 /* VGA channel bypass */426 regmap_update_bits(priv->regmap, 0x2b, VFMT, 9);427 428 /* Output sync polarity. */429 regmap_update_bits(priv->regmap, 0x2e, HPO_O | VPO_O,430 (mode->flags & DRM_MODE_FLAG_PHSYNC) ? HPO_O : 0 |431 (mode->flags & DRM_MODE_FLAG_PVSYNC) ? VPO_O : 0);432 433 /* HDMI horizontal output timing. */434 regmap_update_bits(priv->regmap, 0x54, HWO_HDMI_HI | HOO_HDMI_HI,435 (hsynclen >> 8) << 3 |436 (hbporch >> 8));437 regmap_write(priv->regmap, 0x55, hbporch);438 regmap_write(priv->regmap, 0x56, hsynclen);439 440 /* HDMI vertical output timing. */441 regmap_update_bits(priv->regmap, 0x57, VWO_HDMI_HI | VOO_HDMI_HI,442 (vsynclen >> 8) << 3 |443 (vbporch >> 8));444 regmap_write(priv->regmap, 0x58, vbporch);445 regmap_write(priv->regmap, 0x59, vsynclen);446 447 /* Pick HDMI, not LVDS. */448 regmap_update_bits(priv->regmap, 0x7e, HDMI_LVDS_SEL, HDMI_LVDS_SEL);449 450 /*451 * Page 1452 */453 regmap_write(priv->regmap, 0x03, 0x01);454 455 /* No idea what these do, but VGA is wobbly and blinky without them. */456 regmap_update_bits(priv->regmap, 0x07, CKINV, CKINV);457 regmap_update_bits(priv->regmap, 0x08, DISPON, DISPON);458 459 /* DRI PLL */460 regmap_update_bits(priv->regmap, 0x0c, DRI_PLL_DIVSEL, DRI_PLL_DIVSEL);461 if (mode->clock <= 40000) {462 regmap_update_bits(priv->regmap, 0x0c, DRI_PLL_N1_1 |463 DRI_PLL_N1_0 |464 DRI_PLL_N3_1 |465 DRI_PLL_N3_0,466 0);467 } else if (mode->clock < 80000) {468 regmap_update_bits(priv->regmap, 0x0c, DRI_PLL_N1_1 |469 DRI_PLL_N1_0 |470 DRI_PLL_N3_1 |471 DRI_PLL_N3_0,472 DRI_PLL_N3_0 |473 DRI_PLL_N1_0);474 } else {475 regmap_update_bits(priv->regmap, 0x0c, DRI_PLL_N1_1 |476 DRI_PLL_N1_0 |477 DRI_PLL_N3_1 |478 DRI_PLL_N3_0,479 DRI_PLL_N3_1 |480 DRI_PLL_N1_1);481 }482 483 /* This seems to be color calibration for VGA. */484 regmap_write(priv->regmap, 0x64, 0x29); /* LSB Blue */485 regmap_write(priv->regmap, 0x65, 0x29); /* LSB Green */486 regmap_write(priv->regmap, 0x66, 0x29); /* LSB Red */487 regmap_write(priv->regmap, 0x67, 0x00); /* MSB Blue */488 regmap_write(priv->regmap, 0x68, 0x00); /* MSB Green */489 regmap_write(priv->regmap, 0x69, 0x00); /* MSB Red */490 491 regmap_update_bits(priv->regmap, 0x6b, DRI_PD_SER, 0x00);492 regmap_update_bits(priv->regmap, 0x6c, DRI_PLL_PD, 0x00);493 494 /*495 * Page 3496 */497 regmap_write(priv->regmap, 0x03, 0x03);498 499 /* More bypasses and apparently another HDMI/LVDS selector. */500 regmap_update_bits(priv->regmap, 0x28, VGACLK_BP | HM_LV_SEL,501 VGACLK_BP | HM_LV_SEL);502 regmap_update_bits(priv->regmap, 0x2a, HDMICLK_BP | HDMI_BP,503 HDMICLK_BP | HDMI_BP);504 505 /*506 * Page 4507 */508 regmap_write(priv->regmap, 0x03, 0x04);509 510 /* Output clock. */511 regmap_write(priv->regmap, 0x10, mode->clock >> 16);512 regmap_write(priv->regmap, 0x11, mode->clock >> 8);513 regmap_write(priv->regmap, 0x12, mode->clock);514}515 516static const struct drm_bridge_funcs ch7033_bridge_funcs = {517 .attach = ch7033_bridge_attach,518 .detach = ch7033_bridge_detach,519 .mode_valid = ch7033_bridge_mode_valid,520 .disable = ch7033_bridge_disable,521 .enable = ch7033_bridge_enable,522 .mode_set = ch7033_bridge_mode_set,523};524 525static const struct regmap_config ch7033_regmap_config = {526 .reg_bits = 8,527 .val_bits = 8,528 .max_register = 0x7f,529};530 531static int ch7033_probe(struct i2c_client *client)532{533 struct device *dev = &client->dev;534 struct ch7033_priv *priv;535 unsigned int val;536 int ret;537 538 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);539 if (!priv)540 return -ENOMEM;541 542 dev_set_drvdata(dev, priv);543 544 ret = drm_of_find_panel_or_bridge(dev->of_node, 1, -1, NULL,545 &priv->next_bridge);546 if (ret)547 return ret;548 549 priv->regmap = devm_regmap_init_i2c(client, &ch7033_regmap_config);550 if (IS_ERR(priv->regmap)) {551 dev_err(&client->dev, "regmap init failed\n");552 return PTR_ERR(priv->regmap);553 }554 555 ret = regmap_read(priv->regmap, 0x00, &val);556 if (ret < 0) {557 dev_err(&client->dev, "error reading the model id: %d\n", ret);558 return ret;559 }560 if ((val & 0xf7) != 0x56) {561 dev_err(&client->dev, "the device is not a ch7033\n");562 return -ENODEV;563 }564 565 regmap_write(priv->regmap, 0x03, 0x04);566 ret = regmap_read(priv->regmap, 0x51, &val);567 if (ret < 0) {568 dev_err(&client->dev, "error reading the model id: %d\n", ret);569 return ret;570 }571 if ((val & 0x0f) != 3) {572 dev_err(&client->dev, "unknown revision %u\n", val);573 return -ENODEV;574 }575 576 INIT_LIST_HEAD(&priv->bridge.list);577 priv->bridge.funcs = &ch7033_bridge_funcs;578 priv->bridge.of_node = dev->of_node;579 drm_bridge_add(&priv->bridge);580 581 dev_info(dev, "Chrontel CH7033 Video Encoder\n");582 return 0;583}584 585static void ch7033_remove(struct i2c_client *client)586{587 struct device *dev = &client->dev;588 struct ch7033_priv *priv = dev_get_drvdata(dev);589 590 drm_bridge_remove(&priv->bridge);591}592 593static const struct of_device_id ch7033_dt_ids[] = {594 { .compatible = "chrontel,ch7033", },595 { }596};597MODULE_DEVICE_TABLE(of, ch7033_dt_ids);598 599static const struct i2c_device_id ch7033_ids[] = {600 { "ch7033", 0 },601 { }602};603MODULE_DEVICE_TABLE(i2c, ch7033_ids);604 605static struct i2c_driver ch7033_driver = {606 .probe = ch7033_probe,607 .remove = ch7033_remove,608 .driver = {609 .name = "ch7033",610 .of_match_table = ch7033_dt_ids,611 },612 .id_table = ch7033_ids,613};614 615module_i2c_driver(ch7033_driver);616 617MODULE_AUTHOR("Lubomir Rintel <lkundrak@v3.sk>");618MODULE_DESCRIPTION("Chrontel CH7033 Video Encoder Driver");619MODULE_LICENSE("GPL v2");620