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