root/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. stdp2690_get_edid
  2. ge_b850v3_lvds_get_modes
  3. ge_b850v3_lvds_mode_valid
  4. ge_b850v3_lvds_detect
  5. ge_b850v3_lvds_irq_handler
  6. ge_b850v3_lvds_attach
  7. ge_b850v3_lvds_init
  8. ge_b850v3_lvds_remove
  9. stdp4028_ge_b850v3_fw_probe
  10. stdp4028_ge_b850v3_fw_remove
  11. stdp2690_ge_b850v3_fw_probe
  12. stdp2690_ge_b850v3_fw_remove
  13. stdpxxxx_ge_b850v3_init
  14. stdpxxxx_ge_b850v3_exit

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Driver for MegaChips STDP4028 with GE B850v3 firmware (LVDS-DP)
   4  * Driver for MegaChips STDP2690 with GE B850v3 firmware (DP-DP++)
   5 
   6  * Copyright (c) 2017, Collabora Ltd.
   7  * Copyright (c) 2017, General Electric Company
   8 
   9 
  10  * This driver creates a drm_bridge and a drm_connector for the LVDS to DP++
  11  * display bridge of the GE B850v3. There are two physical bridges on the video
  12  * signal pipeline: a STDP4028(LVDS to DP) and a STDP2690(DP to DP++). The
  13  * physical bridges are automatically configured by the input video signal, and
  14  * the driver has no access to the video processing pipeline. The driver is
  15  * only needed to read EDID from the STDP2690 and to handle HPD events from the
  16  * STDP4028. The driver communicates with both bridges over i2c. The video
  17  * signal pipeline is as follows:
  18  *
  19  *   Host -> LVDS|--(STDP4028)--|DP -> DP|--(STDP2690)--|DP++ -> Video output
  20  */
  21 
  22 #include <linux/i2c.h>
  23 #include <linux/module.h>
  24 #include <linux/of.h>
  25 
  26 #include <drm/drm_atomic.h>
  27 #include <drm/drm_atomic_helper.h>
  28 #include <drm/drm_edid.h>
  29 #include <drm/drm_print.h>
  30 #include <drm/drm_probe_helper.h>
  31 
  32 #define EDID_EXT_BLOCK_CNT 0x7E
  33 
  34 #define STDP4028_IRQ_OUT_CONF_REG 0x02
  35 #define STDP4028_DPTX_IRQ_EN_REG 0x3C
  36 #define STDP4028_DPTX_IRQ_STS_REG 0x3D
  37 #define STDP4028_DPTX_STS_REG 0x3E
  38 
  39 #define STDP4028_DPTX_DP_IRQ_EN 0x1000
  40 
  41 #define STDP4028_DPTX_HOTPLUG_IRQ_EN 0x0400
  42 #define STDP4028_DPTX_LINK_CH_IRQ_EN 0x2000
  43 #define STDP4028_DPTX_IRQ_CONFIG \
  44                 (STDP4028_DPTX_LINK_CH_IRQ_EN | STDP4028_DPTX_HOTPLUG_IRQ_EN)
  45 
  46 #define STDP4028_DPTX_HOTPLUG_STS 0x0200
  47 #define STDP4028_DPTX_LINK_STS 0x1000
  48 #define STDP4028_CON_STATE_CONNECTED \
  49                 (STDP4028_DPTX_HOTPLUG_STS | STDP4028_DPTX_LINK_STS)
  50 
  51 #define STDP4028_DPTX_HOTPLUG_CH_STS 0x0400
  52 #define STDP4028_DPTX_LINK_CH_STS 0x2000
  53 #define STDP4028_DPTX_IRQ_CLEAR \
  54                 (STDP4028_DPTX_LINK_CH_STS | STDP4028_DPTX_HOTPLUG_CH_STS)
  55 
  56 static DEFINE_MUTEX(ge_b850v3_lvds_dev_mutex);
  57 
  58 struct ge_b850v3_lvds {
  59         struct drm_connector connector;
  60         struct drm_bridge bridge;
  61         struct i2c_client *stdp4028_i2c;
  62         struct i2c_client *stdp2690_i2c;
  63         struct edid *edid;
  64 };
  65 
  66 static struct ge_b850v3_lvds *ge_b850v3_lvds_ptr;
  67 
  68 static u8 *stdp2690_get_edid(struct i2c_client *client)
  69 {
  70         struct i2c_adapter *adapter = client->adapter;
  71         unsigned char start = 0x00;
  72         unsigned int total_size;
  73         u8 *block = kmalloc(EDID_LENGTH, GFP_KERNEL);
  74 
  75         struct i2c_msg msgs[] = {
  76                 {
  77                         .addr   = client->addr,
  78                         .flags  = 0,
  79                         .len    = 1,
  80                         .buf    = &start,
  81                 }, {
  82                         .addr   = client->addr,
  83                         .flags  = I2C_M_RD,
  84                         .len    = EDID_LENGTH,
  85                         .buf    = block,
  86                 }
  87         };
  88 
  89         if (!block)
  90                 return NULL;
  91 
  92         if (i2c_transfer(adapter, msgs, 2) != 2) {
  93                 DRM_ERROR("Unable to read EDID.\n");
  94                 goto err;
  95         }
  96 
  97         if (!drm_edid_block_valid(block, 0, false, NULL)) {
  98                 DRM_ERROR("Invalid EDID data\n");
  99                 goto err;
 100         }
 101 
 102         total_size = (block[EDID_EXT_BLOCK_CNT] + 1) * EDID_LENGTH;
 103         if (total_size > EDID_LENGTH) {
 104                 kfree(block);
 105                 block = kmalloc(total_size, GFP_KERNEL);
 106                 if (!block)
 107                         return NULL;
 108 
 109                 /* Yes, read the entire buffer, and do not skip the first
 110                  * EDID_LENGTH bytes.
 111                  */
 112                 start = 0x00;
 113                 msgs[1].len = total_size;
 114                 msgs[1].buf = block;
 115 
 116                 if (i2c_transfer(adapter, msgs, 2) != 2) {
 117                         DRM_ERROR("Unable to read EDID extension blocks.\n");
 118                         goto err;
 119                 }
 120                 if (!drm_edid_block_valid(block, 1, false, NULL)) {
 121                         DRM_ERROR("Invalid EDID data\n");
 122                         goto err;
 123                 }
 124         }
 125 
 126         return block;
 127 
 128 err:
 129         kfree(block);
 130         return NULL;
 131 }
 132 
 133 static int ge_b850v3_lvds_get_modes(struct drm_connector *connector)
 134 {
 135         struct i2c_client *client;
 136         int num_modes = 0;
 137 
 138         client = ge_b850v3_lvds_ptr->stdp2690_i2c;
 139 
 140         kfree(ge_b850v3_lvds_ptr->edid);
 141         ge_b850v3_lvds_ptr->edid = (struct edid *)stdp2690_get_edid(client);
 142 
 143         if (ge_b850v3_lvds_ptr->edid) {
 144                 drm_connector_update_edid_property(connector,
 145                                                       ge_b850v3_lvds_ptr->edid);
 146                 num_modes = drm_add_edid_modes(connector,
 147                                                ge_b850v3_lvds_ptr->edid);
 148         }
 149 
 150         return num_modes;
 151 }
 152 
 153 static enum drm_mode_status ge_b850v3_lvds_mode_valid(
 154                 struct drm_connector *connector, struct drm_display_mode *mode)
 155 {
 156         return MODE_OK;
 157 }
 158 
 159 static const struct
 160 drm_connector_helper_funcs ge_b850v3_lvds_connector_helper_funcs = {
 161         .get_modes = ge_b850v3_lvds_get_modes,
 162         .mode_valid = ge_b850v3_lvds_mode_valid,
 163 };
 164 
 165 static enum drm_connector_status ge_b850v3_lvds_detect(
 166                 struct drm_connector *connector, bool force)
 167 {
 168         struct i2c_client *stdp4028_i2c =
 169                         ge_b850v3_lvds_ptr->stdp4028_i2c;
 170         s32 link_state;
 171 
 172         link_state = i2c_smbus_read_word_data(stdp4028_i2c,
 173                                               STDP4028_DPTX_STS_REG);
 174 
 175         if (link_state == STDP4028_CON_STATE_CONNECTED)
 176                 return connector_status_connected;
 177 
 178         if (link_state == 0)
 179                 return connector_status_disconnected;
 180 
 181         return connector_status_unknown;
 182 }
 183 
 184 static const struct drm_connector_funcs ge_b850v3_lvds_connector_funcs = {
 185         .fill_modes = drm_helper_probe_single_connector_modes,
 186         .detect = ge_b850v3_lvds_detect,
 187         .destroy = drm_connector_cleanup,
 188         .reset = drm_atomic_helper_connector_reset,
 189         .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
 190         .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 191 };
 192 
 193 static irqreturn_t ge_b850v3_lvds_irq_handler(int irq, void *dev_id)
 194 {
 195         struct i2c_client *stdp4028_i2c
 196                         = ge_b850v3_lvds_ptr->stdp4028_i2c;
 197 
 198         i2c_smbus_write_word_data(stdp4028_i2c,
 199                                   STDP4028_DPTX_IRQ_STS_REG,
 200                                   STDP4028_DPTX_IRQ_CLEAR);
 201 
 202         if (ge_b850v3_lvds_ptr->connector.dev)
 203                 drm_kms_helper_hotplug_event(ge_b850v3_lvds_ptr->connector.dev);
 204 
 205         return IRQ_HANDLED;
 206 }
 207 
 208 static int ge_b850v3_lvds_attach(struct drm_bridge *bridge)
 209 {
 210         struct drm_connector *connector = &ge_b850v3_lvds_ptr->connector;
 211         struct i2c_client *stdp4028_i2c
 212                         = ge_b850v3_lvds_ptr->stdp4028_i2c;
 213         int ret;
 214 
 215         if (!bridge->encoder) {
 216                 DRM_ERROR("Parent encoder object not found");
 217                 return -ENODEV;
 218         }
 219 
 220         connector->polled = DRM_CONNECTOR_POLL_HPD;
 221 
 222         drm_connector_helper_add(connector,
 223                                  &ge_b850v3_lvds_connector_helper_funcs);
 224 
 225         ret = drm_connector_init(bridge->dev, connector,
 226                                  &ge_b850v3_lvds_connector_funcs,
 227                                  DRM_MODE_CONNECTOR_DisplayPort);
 228         if (ret) {
 229                 DRM_ERROR("Failed to initialize connector with drm\n");
 230                 return ret;
 231         }
 232 
 233         ret = drm_connector_attach_encoder(connector, bridge->encoder);
 234         if (ret)
 235                 return ret;
 236 
 237         /* Configures the bridge to re-enable interrupts after each ack. */
 238         i2c_smbus_write_word_data(stdp4028_i2c,
 239                                   STDP4028_IRQ_OUT_CONF_REG,
 240                                   STDP4028_DPTX_DP_IRQ_EN);
 241 
 242         /* Enable interrupts */
 243         i2c_smbus_write_word_data(stdp4028_i2c,
 244                                   STDP4028_DPTX_IRQ_EN_REG,
 245                                   STDP4028_DPTX_IRQ_CONFIG);
 246 
 247         return 0;
 248 }
 249 
 250 static const struct drm_bridge_funcs ge_b850v3_lvds_funcs = {
 251         .attach = ge_b850v3_lvds_attach,
 252 };
 253 
 254 static int ge_b850v3_lvds_init(struct device *dev)
 255 {
 256         mutex_lock(&ge_b850v3_lvds_dev_mutex);
 257 
 258         if (ge_b850v3_lvds_ptr)
 259                 goto success;
 260 
 261         ge_b850v3_lvds_ptr = devm_kzalloc(dev,
 262                                           sizeof(*ge_b850v3_lvds_ptr),
 263                                           GFP_KERNEL);
 264 
 265         if (!ge_b850v3_lvds_ptr) {
 266                 mutex_unlock(&ge_b850v3_lvds_dev_mutex);
 267                 return -ENOMEM;
 268         }
 269 
 270 success:
 271         mutex_unlock(&ge_b850v3_lvds_dev_mutex);
 272         return 0;
 273 }
 274 
 275 static void ge_b850v3_lvds_remove(void)
 276 {
 277         mutex_lock(&ge_b850v3_lvds_dev_mutex);
 278         /*
 279          * This check is to avoid both the drivers
 280          * removing the bridge in their remove() function
 281          */
 282         if (!ge_b850v3_lvds_ptr)
 283                 goto out;
 284 
 285         drm_bridge_remove(&ge_b850v3_lvds_ptr->bridge);
 286 
 287         kfree(ge_b850v3_lvds_ptr->edid);
 288 
 289         ge_b850v3_lvds_ptr = NULL;
 290 out:
 291         mutex_unlock(&ge_b850v3_lvds_dev_mutex);
 292 }
 293 
 294 static int stdp4028_ge_b850v3_fw_probe(struct i2c_client *stdp4028_i2c,
 295                                        const struct i2c_device_id *id)
 296 {
 297         struct device *dev = &stdp4028_i2c->dev;
 298 
 299         ge_b850v3_lvds_init(dev);
 300 
 301         ge_b850v3_lvds_ptr->stdp4028_i2c = stdp4028_i2c;
 302         i2c_set_clientdata(stdp4028_i2c, ge_b850v3_lvds_ptr);
 303 
 304         /* drm bridge initialization */
 305         ge_b850v3_lvds_ptr->bridge.funcs = &ge_b850v3_lvds_funcs;
 306         ge_b850v3_lvds_ptr->bridge.of_node = dev->of_node;
 307         drm_bridge_add(&ge_b850v3_lvds_ptr->bridge);
 308 
 309         /* Clear pending interrupts since power up. */
 310         i2c_smbus_write_word_data(stdp4028_i2c,
 311                                   STDP4028_DPTX_IRQ_STS_REG,
 312                                   STDP4028_DPTX_IRQ_CLEAR);
 313 
 314         if (!stdp4028_i2c->irq)
 315                 return 0;
 316 
 317         return devm_request_threaded_irq(&stdp4028_i2c->dev,
 318                         stdp4028_i2c->irq, NULL,
 319                         ge_b850v3_lvds_irq_handler,
 320                         IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
 321                         "ge-b850v3-lvds-dp", ge_b850v3_lvds_ptr);
 322 }
 323 
 324 static int stdp4028_ge_b850v3_fw_remove(struct i2c_client *stdp4028_i2c)
 325 {
 326         ge_b850v3_lvds_remove();
 327 
 328         return 0;
 329 }
 330 
 331 static const struct i2c_device_id stdp4028_ge_b850v3_fw_i2c_table[] = {
 332         {"stdp4028_ge_fw", 0},
 333         {},
 334 };
 335 MODULE_DEVICE_TABLE(i2c, stdp4028_ge_b850v3_fw_i2c_table);
 336 
 337 static const struct of_device_id stdp4028_ge_b850v3_fw_match[] = {
 338         { .compatible = "megachips,stdp4028-ge-b850v3-fw" },
 339         {},
 340 };
 341 MODULE_DEVICE_TABLE(of, stdp4028_ge_b850v3_fw_match);
 342 
 343 static struct i2c_driver stdp4028_ge_b850v3_fw_driver = {
 344         .id_table       = stdp4028_ge_b850v3_fw_i2c_table,
 345         .probe          = stdp4028_ge_b850v3_fw_probe,
 346         .remove         = stdp4028_ge_b850v3_fw_remove,
 347         .driver         = {
 348                 .name           = "stdp4028-ge-b850v3-fw",
 349                 .of_match_table = stdp4028_ge_b850v3_fw_match,
 350         },
 351 };
 352 
 353 static int stdp2690_ge_b850v3_fw_probe(struct i2c_client *stdp2690_i2c,
 354                                        const struct i2c_device_id *id)
 355 {
 356         struct device *dev = &stdp2690_i2c->dev;
 357 
 358         ge_b850v3_lvds_init(dev);
 359 
 360         ge_b850v3_lvds_ptr->stdp2690_i2c = stdp2690_i2c;
 361         i2c_set_clientdata(stdp2690_i2c, ge_b850v3_lvds_ptr);
 362 
 363         return 0;
 364 }
 365 
 366 static int stdp2690_ge_b850v3_fw_remove(struct i2c_client *stdp2690_i2c)
 367 {
 368         ge_b850v3_lvds_remove();
 369 
 370         return 0;
 371 }
 372 
 373 static const struct i2c_device_id stdp2690_ge_b850v3_fw_i2c_table[] = {
 374         {"stdp2690_ge_fw", 0},
 375         {},
 376 };
 377 MODULE_DEVICE_TABLE(i2c, stdp2690_ge_b850v3_fw_i2c_table);
 378 
 379 static const struct of_device_id stdp2690_ge_b850v3_fw_match[] = {
 380         { .compatible = "megachips,stdp2690-ge-b850v3-fw" },
 381         {},
 382 };
 383 MODULE_DEVICE_TABLE(of, stdp2690_ge_b850v3_fw_match);
 384 
 385 static struct i2c_driver stdp2690_ge_b850v3_fw_driver = {
 386         .id_table       = stdp2690_ge_b850v3_fw_i2c_table,
 387         .probe          = stdp2690_ge_b850v3_fw_probe,
 388         .remove         = stdp2690_ge_b850v3_fw_remove,
 389         .driver         = {
 390                 .name           = "stdp2690-ge-b850v3-fw",
 391                 .of_match_table = stdp2690_ge_b850v3_fw_match,
 392         },
 393 };
 394 
 395 static int __init stdpxxxx_ge_b850v3_init(void)
 396 {
 397         int ret;
 398 
 399         ret = i2c_add_driver(&stdp4028_ge_b850v3_fw_driver);
 400         if (ret)
 401                 return ret;
 402 
 403         return i2c_add_driver(&stdp2690_ge_b850v3_fw_driver);
 404 }
 405 module_init(stdpxxxx_ge_b850v3_init);
 406 
 407 static void __exit stdpxxxx_ge_b850v3_exit(void)
 408 {
 409         i2c_del_driver(&stdp2690_ge_b850v3_fw_driver);
 410         i2c_del_driver(&stdp4028_ge_b850v3_fw_driver);
 411 }
 412 module_exit(stdpxxxx_ge_b850v3_exit);
 413 
 414 MODULE_AUTHOR("Peter Senna Tschudin <peter.senna@collabora.com>");
 415 MODULE_AUTHOR("Martyn Welch <martyn.welch@collabora.co.uk>");
 416 MODULE_DESCRIPTION("GE LVDS to DP++ display bridge)");
 417 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */