linux/drivers/gpu/drm/bridge/sii902x.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Copyright (C) 2018 Renesas Electronics
   4 *
   5 * Copyright (C) 2016 Atmel
   6 *                    Bo Shen <voice.shen@atmel.com>
   7 *
   8 * Authors:           Bo Shen <voice.shen@atmel.com>
   9 *                    Boris Brezillon <boris.brezillon@free-electrons.com>
  10 *                    Wu, Songjun <Songjun.Wu@atmel.com>
  11 *
  12 * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved.
  13 */
  14
  15#include <linux/gpio/consumer.h>
  16#include <linux/i2c-mux.h>
  17#include <linux/i2c.h>
  18#include <linux/module.h>
  19#include <linux/regmap.h>
  20
  21#include <drm/drmP.h>
  22#include <drm/drm_atomic_helper.h>
  23#include <drm/drm_edid.h>
  24#include <drm/drm_probe_helper.h>
  25
  26#define SII902X_TPI_VIDEO_DATA                  0x0
  27
  28#define SII902X_TPI_PIXEL_REPETITION            0x8
  29#define SII902X_TPI_AVI_PIXEL_REP_BUS_24BIT     BIT(5)
  30#define SII902X_TPI_AVI_PIXEL_REP_RISING_EDGE   BIT(4)
  31#define SII902X_TPI_AVI_PIXEL_REP_4X            3
  32#define SII902X_TPI_AVI_PIXEL_REP_2X            1
  33#define SII902X_TPI_AVI_PIXEL_REP_NONE          0
  34#define SII902X_TPI_CLK_RATIO_HALF              (0 << 6)
  35#define SII902X_TPI_CLK_RATIO_1X                (1 << 6)
  36#define SII902X_TPI_CLK_RATIO_2X                (2 << 6)
  37#define SII902X_TPI_CLK_RATIO_4X                (3 << 6)
  38
  39#define SII902X_TPI_AVI_IN_FORMAT               0x9
  40#define SII902X_TPI_AVI_INPUT_BITMODE_12BIT     BIT(7)
  41#define SII902X_TPI_AVI_INPUT_DITHER            BIT(6)
  42#define SII902X_TPI_AVI_INPUT_RANGE_LIMITED     (2 << 2)
  43#define SII902X_TPI_AVI_INPUT_RANGE_FULL        (1 << 2)
  44#define SII902X_TPI_AVI_INPUT_RANGE_AUTO        (0 << 2)
  45#define SII902X_TPI_AVI_INPUT_COLORSPACE_BLACK  (3 << 0)
  46#define SII902X_TPI_AVI_INPUT_COLORSPACE_YUV422 (2 << 0)
  47#define SII902X_TPI_AVI_INPUT_COLORSPACE_YUV444 (1 << 0)
  48#define SII902X_TPI_AVI_INPUT_COLORSPACE_RGB    (0 << 0)
  49
  50#define SII902X_TPI_AVI_INFOFRAME               0x0c
  51
  52#define SII902X_SYS_CTRL_DATA                   0x1a
  53#define SII902X_SYS_CTRL_PWR_DWN                BIT(4)
  54#define SII902X_SYS_CTRL_AV_MUTE                BIT(3)
  55#define SII902X_SYS_CTRL_DDC_BUS_REQ            BIT(2)
  56#define SII902X_SYS_CTRL_DDC_BUS_GRTD           BIT(1)
  57#define SII902X_SYS_CTRL_OUTPUT_MODE            BIT(0)
  58#define SII902X_SYS_CTRL_OUTPUT_HDMI            1
  59#define SII902X_SYS_CTRL_OUTPUT_DVI             0
  60
  61#define SII902X_REG_CHIPID(n)                   (0x1b + (n))
  62
  63#define SII902X_PWR_STATE_CTRL                  0x1e
  64#define SII902X_AVI_POWER_STATE_MSK             GENMASK(1, 0)
  65#define SII902X_AVI_POWER_STATE_D(l)            ((l) & SII902X_AVI_POWER_STATE_MSK)
  66
  67#define SII902X_INT_ENABLE                      0x3c
  68#define SII902X_INT_STATUS                      0x3d
  69#define SII902X_HOTPLUG_EVENT                   BIT(0)
  70#define SII902X_PLUGGED_STATUS                  BIT(2)
  71
  72#define SII902X_REG_TPI_RQB                     0xc7
  73
  74#define SII902X_I2C_BUS_ACQUISITION_TIMEOUT_MS  500
  75
  76struct sii902x {
  77        struct i2c_client *i2c;
  78        struct regmap *regmap;
  79        struct drm_bridge bridge;
  80        struct drm_connector connector;
  81        struct gpio_desc *reset_gpio;
  82        struct i2c_mux_core *i2cmux;
  83};
  84
  85static int sii902x_read_unlocked(struct i2c_client *i2c, u8 reg, u8 *val)
  86{
  87        union i2c_smbus_data data;
  88        int ret;
  89
  90        ret = __i2c_smbus_xfer(i2c->adapter, i2c->addr, i2c->flags,
  91                               I2C_SMBUS_READ, reg, I2C_SMBUS_BYTE_DATA, &data);
  92
  93        if (ret < 0)
  94                return ret;
  95
  96        *val = data.byte;
  97        return 0;
  98}
  99
 100static int sii902x_write_unlocked(struct i2c_client *i2c, u8 reg, u8 val)
 101{
 102        union i2c_smbus_data data;
 103
 104        data.byte = val;
 105
 106        return __i2c_smbus_xfer(i2c->adapter, i2c->addr, i2c->flags,
 107                                I2C_SMBUS_WRITE, reg, I2C_SMBUS_BYTE_DATA,
 108                                &data);
 109}
 110
 111static int sii902x_update_bits_unlocked(struct i2c_client *i2c, u8 reg, u8 mask,
 112                                        u8 val)
 113{
 114        int ret;
 115        u8 status;
 116
 117        ret = sii902x_read_unlocked(i2c, reg, &status);
 118        if (ret)
 119                return ret;
 120        status &= ~mask;
 121        status |= val & mask;
 122        return sii902x_write_unlocked(i2c, reg, status);
 123}
 124
 125static inline struct sii902x *bridge_to_sii902x(struct drm_bridge *bridge)
 126{
 127        return container_of(bridge, struct sii902x, bridge);
 128}
 129
 130static inline struct sii902x *connector_to_sii902x(struct drm_connector *con)
 131{
 132        return container_of(con, struct sii902x, connector);
 133}
 134
 135static void sii902x_reset(struct sii902x *sii902x)
 136{
 137        if (!sii902x->reset_gpio)
 138                return;
 139
 140        gpiod_set_value(sii902x->reset_gpio, 1);
 141
 142        /* The datasheet says treset-min = 100us. Make it 150us to be sure. */
 143        usleep_range(150, 200);
 144
 145        gpiod_set_value(sii902x->reset_gpio, 0);
 146}
 147
 148static enum drm_connector_status
 149sii902x_connector_detect(struct drm_connector *connector, bool force)
 150{
 151        struct sii902x *sii902x = connector_to_sii902x(connector);
 152        unsigned int status;
 153
 154        regmap_read(sii902x->regmap, SII902X_INT_STATUS, &status);
 155
 156        return (status & SII902X_PLUGGED_STATUS) ?
 157               connector_status_connected : connector_status_disconnected;
 158}
 159
 160static const struct drm_connector_funcs sii902x_connector_funcs = {
 161        .detect = sii902x_connector_detect,
 162        .fill_modes = drm_helper_probe_single_connector_modes,
 163        .destroy = drm_connector_cleanup,
 164        .reset = drm_atomic_helper_connector_reset,
 165        .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
 166        .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 167};
 168
 169static int sii902x_get_modes(struct drm_connector *connector)
 170{
 171        struct sii902x *sii902x = connector_to_sii902x(connector);
 172        u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
 173        struct edid *edid;
 174        int num = 0, ret;
 175
 176        edid = drm_get_edid(connector, sii902x->i2cmux->adapter[0]);
 177        drm_connector_update_edid_property(connector, edid);
 178        if (edid) {
 179                num = drm_add_edid_modes(connector, edid);
 180                kfree(edid);
 181        }
 182
 183        ret = drm_display_info_set_bus_formats(&connector->display_info,
 184                                               &bus_format, 1);
 185        if (ret)
 186                return ret;
 187
 188        return num;
 189}
 190
 191static enum drm_mode_status sii902x_mode_valid(struct drm_connector *connector,
 192                                               struct drm_display_mode *mode)
 193{
 194        /* TODO: check mode */
 195
 196        return MODE_OK;
 197}
 198
 199static const struct drm_connector_helper_funcs sii902x_connector_helper_funcs = {
 200        .get_modes = sii902x_get_modes,
 201        .mode_valid = sii902x_mode_valid,
 202};
 203
 204static void sii902x_bridge_disable(struct drm_bridge *bridge)
 205{
 206        struct sii902x *sii902x = bridge_to_sii902x(bridge);
 207
 208        regmap_update_bits(sii902x->regmap, SII902X_SYS_CTRL_DATA,
 209                           SII902X_SYS_CTRL_PWR_DWN,
 210                           SII902X_SYS_CTRL_PWR_DWN);
 211}
 212
 213static void sii902x_bridge_enable(struct drm_bridge *bridge)
 214{
 215        struct sii902x *sii902x = bridge_to_sii902x(bridge);
 216
 217        regmap_update_bits(sii902x->regmap, SII902X_PWR_STATE_CTRL,
 218                           SII902X_AVI_POWER_STATE_MSK,
 219                           SII902X_AVI_POWER_STATE_D(0));
 220        regmap_update_bits(sii902x->regmap, SII902X_SYS_CTRL_DATA,
 221                           SII902X_SYS_CTRL_PWR_DWN, 0);
 222}
 223
 224static void sii902x_bridge_mode_set(struct drm_bridge *bridge,
 225                                    const struct drm_display_mode *mode,
 226                                    const struct drm_display_mode *adj)
 227{
 228        struct sii902x *sii902x = bridge_to_sii902x(bridge);
 229        struct regmap *regmap = sii902x->regmap;
 230        u8 buf[HDMI_INFOFRAME_SIZE(AVI)];
 231        struct hdmi_avi_infoframe frame;
 232        int ret;
 233
 234        buf[0] = adj->clock;
 235        buf[1] = adj->clock >> 8;
 236        buf[2] = adj->vrefresh;
 237        buf[3] = 0x00;
 238        buf[4] = adj->hdisplay;
 239        buf[5] = adj->hdisplay >> 8;
 240        buf[6] = adj->vdisplay;
 241        buf[7] = adj->vdisplay >> 8;
 242        buf[8] = SII902X_TPI_CLK_RATIO_1X | SII902X_TPI_AVI_PIXEL_REP_NONE |
 243                 SII902X_TPI_AVI_PIXEL_REP_BUS_24BIT;
 244        buf[9] = SII902X_TPI_AVI_INPUT_RANGE_AUTO |
 245                 SII902X_TPI_AVI_INPUT_COLORSPACE_RGB;
 246
 247        ret = regmap_bulk_write(regmap, SII902X_TPI_VIDEO_DATA, buf, 10);
 248        if (ret)
 249                return;
 250
 251        ret = drm_hdmi_avi_infoframe_from_display_mode(&frame,
 252                                                       &sii902x->connector, adj);
 253        if (ret < 0) {
 254                DRM_ERROR("couldn't fill AVI infoframe\n");
 255                return;
 256        }
 257
 258        ret = hdmi_avi_infoframe_pack(&frame, buf, sizeof(buf));
 259        if (ret < 0) {
 260                DRM_ERROR("failed to pack AVI infoframe: %d\n", ret);
 261                return;
 262        }
 263
 264        /* Do not send the infoframe header, but keep the CRC field. */
 265        regmap_bulk_write(regmap, SII902X_TPI_AVI_INFOFRAME,
 266                          buf + HDMI_INFOFRAME_HEADER_SIZE - 1,
 267                          HDMI_AVI_INFOFRAME_SIZE + 1);
 268}
 269
 270static int sii902x_bridge_attach(struct drm_bridge *bridge)
 271{
 272        struct sii902x *sii902x = bridge_to_sii902x(bridge);
 273        struct drm_device *drm = bridge->dev;
 274        int ret;
 275
 276        drm_connector_helper_add(&sii902x->connector,
 277                                 &sii902x_connector_helper_funcs);
 278
 279        if (!drm_core_check_feature(drm, DRIVER_ATOMIC)) {
 280                dev_err(&sii902x->i2c->dev,
 281                        "sii902x driver is only compatible with DRM devices supporting atomic updates\n");
 282                return -ENOTSUPP;
 283        }
 284
 285        ret = drm_connector_init(drm, &sii902x->connector,
 286                                 &sii902x_connector_funcs,
 287                                 DRM_MODE_CONNECTOR_HDMIA);
 288        if (ret)
 289                return ret;
 290
 291        if (sii902x->i2c->irq > 0)
 292                sii902x->connector.polled = DRM_CONNECTOR_POLL_HPD;
 293        else
 294                sii902x->connector.polled = DRM_CONNECTOR_POLL_CONNECT;
 295
 296        drm_connector_attach_encoder(&sii902x->connector, bridge->encoder);
 297
 298        return 0;
 299}
 300
 301static const struct drm_bridge_funcs sii902x_bridge_funcs = {
 302        .attach = sii902x_bridge_attach,
 303        .mode_set = sii902x_bridge_mode_set,
 304        .disable = sii902x_bridge_disable,
 305        .enable = sii902x_bridge_enable,
 306};
 307
 308static const struct regmap_range sii902x_volatile_ranges[] = {
 309        { .range_min = 0, .range_max = 0xff },
 310};
 311
 312static const struct regmap_access_table sii902x_volatile_table = {
 313        .yes_ranges = sii902x_volatile_ranges,
 314        .n_yes_ranges = ARRAY_SIZE(sii902x_volatile_ranges),
 315};
 316
 317static const struct regmap_config sii902x_regmap_config = {
 318        .reg_bits = 8,
 319        .val_bits = 8,
 320        .volatile_table = &sii902x_volatile_table,
 321        .cache_type = REGCACHE_NONE,
 322};
 323
 324static irqreturn_t sii902x_interrupt(int irq, void *data)
 325{
 326        struct sii902x *sii902x = data;
 327        unsigned int status = 0;
 328
 329        regmap_read(sii902x->regmap, SII902X_INT_STATUS, &status);
 330        regmap_write(sii902x->regmap, SII902X_INT_STATUS, status);
 331
 332        if ((status & SII902X_HOTPLUG_EVENT) && sii902x->bridge.dev)
 333                drm_helper_hpd_irq_event(sii902x->bridge.dev);
 334
 335        return IRQ_HANDLED;
 336}
 337
 338/*
 339 * The purpose of sii902x_i2c_bypass_select is to enable the pass through
 340 * mode of the HDMI transmitter. Do not use regmap from within this function,
 341 * only use sii902x_*_unlocked functions to read/modify/write registers.
 342 * We are holding the parent adapter lock here, keep this in mind before
 343 * adding more i2c transactions.
 344 *
 345 * Also, since SII902X_SYS_CTRL_DATA is used with regmap_update_bits elsewhere
 346 * in this driver, we need to make sure that we only touch 0x1A[2:1] from
 347 * within sii902x_i2c_bypass_select and sii902x_i2c_bypass_deselect, and that
 348 * we leave the remaining bits as we have found them.
 349 */
 350static int sii902x_i2c_bypass_select(struct i2c_mux_core *mux, u32 chan_id)
 351{
 352        struct sii902x *sii902x = i2c_mux_priv(mux);
 353        struct device *dev = &sii902x->i2c->dev;
 354        unsigned long timeout;
 355        u8 status;
 356        int ret;
 357
 358        ret = sii902x_update_bits_unlocked(sii902x->i2c, SII902X_SYS_CTRL_DATA,
 359                                           SII902X_SYS_CTRL_DDC_BUS_REQ,
 360                                           SII902X_SYS_CTRL_DDC_BUS_REQ);
 361        if (ret)
 362                return ret;
 363
 364        timeout = jiffies +
 365                  msecs_to_jiffies(SII902X_I2C_BUS_ACQUISITION_TIMEOUT_MS);
 366        do {
 367                ret = sii902x_read_unlocked(sii902x->i2c, SII902X_SYS_CTRL_DATA,
 368                                            &status);
 369                if (ret)
 370                        return ret;
 371        } while (!(status & SII902X_SYS_CTRL_DDC_BUS_GRTD) &&
 372                 time_before(jiffies, timeout));
 373
 374        if (!(status & SII902X_SYS_CTRL_DDC_BUS_GRTD)) {
 375                dev_err(dev, "Failed to acquire the i2c bus\n");
 376                return -ETIMEDOUT;
 377        }
 378
 379        return sii902x_write_unlocked(sii902x->i2c, SII902X_SYS_CTRL_DATA,
 380                                      status);
 381}
 382
 383/*
 384 * The purpose of sii902x_i2c_bypass_deselect is to disable the pass through
 385 * mode of the HDMI transmitter. Do not use regmap from within this function,
 386 * only use sii902x_*_unlocked functions to read/modify/write registers.
 387 * We are holding the parent adapter lock here, keep this in mind before
 388 * adding more i2c transactions.
 389 *
 390 * Also, since SII902X_SYS_CTRL_DATA is used with regmap_update_bits elsewhere
 391 * in this driver, we need to make sure that we only touch 0x1A[2:1] from
 392 * within sii902x_i2c_bypass_select and sii902x_i2c_bypass_deselect, and that
 393 * we leave the remaining bits as we have found them.
 394 */
 395static int sii902x_i2c_bypass_deselect(struct i2c_mux_core *mux, u32 chan_id)
 396{
 397        struct sii902x *sii902x = i2c_mux_priv(mux);
 398        struct device *dev = &sii902x->i2c->dev;
 399        unsigned long timeout;
 400        unsigned int retries;
 401        u8 status;
 402        int ret;
 403
 404        /*
 405         * When the HDMI transmitter is in pass through mode, we need an
 406         * (undocumented) additional delay between STOP and START conditions
 407         * to guarantee the bus won't get stuck.
 408         */
 409        udelay(30);
 410
 411        /*
 412         * Sometimes the I2C bus can stall after failure to use the
 413         * EDID channel. Retry a few times to see if things clear
 414         * up, else continue anyway.
 415         */
 416        retries = 5;
 417        do {
 418                ret = sii902x_read_unlocked(sii902x->i2c, SII902X_SYS_CTRL_DATA,
 419                                            &status);
 420                retries--;
 421        } while (ret && retries);
 422        if (ret) {
 423                dev_err(dev, "failed to read status (%d)\n", ret);
 424                return ret;
 425        }
 426
 427        ret = sii902x_update_bits_unlocked(sii902x->i2c, SII902X_SYS_CTRL_DATA,
 428                                           SII902X_SYS_CTRL_DDC_BUS_REQ |
 429                                           SII902X_SYS_CTRL_DDC_BUS_GRTD, 0);
 430        if (ret)
 431                return ret;
 432
 433        timeout = jiffies +
 434                  msecs_to_jiffies(SII902X_I2C_BUS_ACQUISITION_TIMEOUT_MS);
 435        do {
 436                ret = sii902x_read_unlocked(sii902x->i2c, SII902X_SYS_CTRL_DATA,
 437                                            &status);
 438                if (ret)
 439                        return ret;
 440        } while (status & (SII902X_SYS_CTRL_DDC_BUS_REQ |
 441                           SII902X_SYS_CTRL_DDC_BUS_GRTD) &&
 442                 time_before(jiffies, timeout));
 443
 444        if (status & (SII902X_SYS_CTRL_DDC_BUS_REQ |
 445                      SII902X_SYS_CTRL_DDC_BUS_GRTD)) {
 446                dev_err(dev, "failed to release the i2c bus\n");
 447                return -ETIMEDOUT;
 448        }
 449
 450        return 0;
 451}
 452
 453static int sii902x_probe(struct i2c_client *client,
 454                         const struct i2c_device_id *id)
 455{
 456        struct device *dev = &client->dev;
 457        unsigned int status = 0;
 458        struct sii902x *sii902x;
 459        u8 chipid[4];
 460        int ret;
 461
 462        ret = i2c_check_functionality(client->adapter,
 463                                      I2C_FUNC_SMBUS_BYTE_DATA);
 464        if (!ret) {
 465                dev_err(dev, "I2C adapter not suitable\n");
 466                return -EIO;
 467        }
 468
 469        sii902x = devm_kzalloc(dev, sizeof(*sii902x), GFP_KERNEL);
 470        if (!sii902x)
 471                return -ENOMEM;
 472
 473        sii902x->i2c = client;
 474        sii902x->regmap = devm_regmap_init_i2c(client, &sii902x_regmap_config);
 475        if (IS_ERR(sii902x->regmap))
 476                return PTR_ERR(sii902x->regmap);
 477
 478        sii902x->reset_gpio = devm_gpiod_get_optional(dev, "reset",
 479                                                      GPIOD_OUT_LOW);
 480        if (IS_ERR(sii902x->reset_gpio)) {
 481                dev_err(dev, "Failed to retrieve/request reset gpio: %ld\n",
 482                        PTR_ERR(sii902x->reset_gpio));
 483                return PTR_ERR(sii902x->reset_gpio);
 484        }
 485
 486        sii902x_reset(sii902x);
 487
 488        ret = regmap_write(sii902x->regmap, SII902X_REG_TPI_RQB, 0x0);
 489        if (ret)
 490                return ret;
 491
 492        ret = regmap_bulk_read(sii902x->regmap, SII902X_REG_CHIPID(0),
 493                               &chipid, 4);
 494        if (ret) {
 495                dev_err(dev, "regmap_read failed %d\n", ret);
 496                return ret;
 497        }
 498
 499        if (chipid[0] != 0xb0) {
 500                dev_err(dev, "Invalid chipid: %02x (expecting 0xb0)\n",
 501                        chipid[0]);
 502                return -EINVAL;
 503        }
 504
 505        /* Clear all pending interrupts */
 506        regmap_read(sii902x->regmap, SII902X_INT_STATUS, &status);
 507        regmap_write(sii902x->regmap, SII902X_INT_STATUS, status);
 508
 509        if (client->irq > 0) {
 510                regmap_write(sii902x->regmap, SII902X_INT_ENABLE,
 511                             SII902X_HOTPLUG_EVENT);
 512
 513                ret = devm_request_threaded_irq(dev, client->irq, NULL,
 514                                                sii902x_interrupt,
 515                                                IRQF_ONESHOT, dev_name(dev),
 516                                                sii902x);
 517                if (ret)
 518                        return ret;
 519        }
 520
 521        sii902x->bridge.funcs = &sii902x_bridge_funcs;
 522        sii902x->bridge.of_node = dev->of_node;
 523        drm_bridge_add(&sii902x->bridge);
 524
 525        i2c_set_clientdata(client, sii902x);
 526
 527        sii902x->i2cmux = i2c_mux_alloc(client->adapter, dev,
 528                                        1, 0, I2C_MUX_GATE,
 529                                        sii902x_i2c_bypass_select,
 530                                        sii902x_i2c_bypass_deselect);
 531        if (!sii902x->i2cmux)
 532                return -ENOMEM;
 533
 534        sii902x->i2cmux->priv = sii902x;
 535        return i2c_mux_add_adapter(sii902x->i2cmux, 0, 0, 0);
 536}
 537
 538static int sii902x_remove(struct i2c_client *client)
 539
 540{
 541        struct sii902x *sii902x = i2c_get_clientdata(client);
 542
 543        i2c_mux_del_adapters(sii902x->i2cmux);
 544        drm_bridge_remove(&sii902x->bridge);
 545
 546        return 0;
 547}
 548
 549static const struct of_device_id sii902x_dt_ids[] = {
 550        { .compatible = "sil,sii9022", },
 551        { }
 552};
 553MODULE_DEVICE_TABLE(of, sii902x_dt_ids);
 554
 555static const struct i2c_device_id sii902x_i2c_ids[] = {
 556        { "sii9022", 0 },
 557        { },
 558};
 559MODULE_DEVICE_TABLE(i2c, sii902x_i2c_ids);
 560
 561static struct i2c_driver sii902x_driver = {
 562        .probe = sii902x_probe,
 563        .remove = sii902x_remove,
 564        .driver = {
 565                .name = "sii902x",
 566                .of_match_table = sii902x_dt_ids,
 567        },
 568        .id_table = sii902x_i2c_ids,
 569};
 570module_i2c_driver(sii902x_driver);
 571
 572MODULE_AUTHOR("Boris Brezillon <boris.brezillon@free-electrons.com>");
 573MODULE_DESCRIPTION("SII902x RGB -> HDMI bridges");
 574MODULE_LICENSE("GPL");
 575