root/drivers/gpu/drm/i2c/sil164_drv.c

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

DEFINITIONS

This source file includes following definitions.
  1. sil164_write
  2. sil164_read
  3. sil164_save_state
  4. sil164_restore_state
  5. sil164_set_power_state
  6. sil164_init_state
  7. sil164_encoder_set_config
  8. sil164_encoder_dpms
  9. sil164_encoder_save
  10. sil164_encoder_restore
  11. sil164_encoder_mode_valid
  12. sil164_encoder_mode_set
  13. sil164_encoder_detect
  14. sil164_encoder_get_modes
  15. sil164_encoder_create_resources
  16. sil164_encoder_set_property
  17. sil164_encoder_destroy
  18. sil164_probe
  19. sil164_remove
  20. sil164_detect_slave
  21. sil164_encoder_init
  22. sil164_init
  23. sil164_exit

   1 /*
   2  * Copyright (C) 2010 Francisco Jerez.
   3  * All Rights Reserved.
   4  *
   5  * Permission is hereby granted, free of charge, to any person obtaining
   6  * a copy of this software and associated documentation files (the
   7  * "Software"), to deal in the Software without restriction, including
   8  * without limitation the rights to use, copy, modify, merge, publish,
   9  * distribute, sublicense, and/or sell copies of the Software, and to
  10  * permit persons to whom the Software is furnished to do so, subject to
  11  * the following conditions:
  12  *
  13  * The above copyright notice and this permission notice (including the
  14  * next paragraph) shall be included in all copies or substantial
  15  * portions of the Software.
  16  *
  17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  20  * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
  21  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  22  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  23  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  24  *
  25  */
  26 
  27 #include <linux/module.h>
  28 
  29 #include <drm/drm_drv.h>
  30 #include <drm/drm_encoder_slave.h>
  31 #include <drm/drm_print.h>
  32 #include <drm/drm_probe_helper.h>
  33 #include <drm/i2c/sil164.h>
  34 
  35 struct sil164_priv {
  36         struct sil164_encoder_params config;
  37         struct i2c_client *duallink_slave;
  38 
  39         uint8_t saved_state[0x10];
  40         uint8_t saved_slave_state[0x10];
  41 };
  42 
  43 #define to_sil164_priv(x) \
  44         ((struct sil164_priv *)to_encoder_slave(x)->slave_priv)
  45 
  46 #define sil164_dbg(client, format, ...) do {                            \
  47                 if (drm_debug & DRM_UT_KMS)                             \
  48                         dev_printk(KERN_DEBUG, &client->dev,            \
  49                                    "%s: " format, __func__, ## __VA_ARGS__); \
  50         } while (0)
  51 #define sil164_info(client, format, ...)                \
  52         dev_info(&client->dev, format, __VA_ARGS__)
  53 #define sil164_err(client, format, ...)                 \
  54         dev_err(&client->dev, format, __VA_ARGS__)
  55 
  56 #define SIL164_I2C_ADDR_MASTER                  0x38
  57 #define SIL164_I2C_ADDR_SLAVE                   0x39
  58 
  59 /* HW register definitions */
  60 
  61 #define SIL164_VENDOR_LO                        0x0
  62 #define SIL164_VENDOR_HI                        0x1
  63 #define SIL164_DEVICE_LO                        0x2
  64 #define SIL164_DEVICE_HI                        0x3
  65 #define SIL164_REVISION                         0x4
  66 #define SIL164_FREQ_MIN                         0x6
  67 #define SIL164_FREQ_MAX                         0x7
  68 #define SIL164_CONTROL0                         0x8
  69 #  define SIL164_CONTROL0_POWER_ON              0x01
  70 #  define SIL164_CONTROL0_EDGE_RISING           0x02
  71 #  define SIL164_CONTROL0_INPUT_24BIT           0x04
  72 #  define SIL164_CONTROL0_DUAL_EDGE             0x08
  73 #  define SIL164_CONTROL0_HSYNC_ON              0x10
  74 #  define SIL164_CONTROL0_VSYNC_ON              0x20
  75 #define SIL164_DETECT                           0x9
  76 #  define SIL164_DETECT_INTR_STAT               0x01
  77 #  define SIL164_DETECT_HOTPLUG_STAT            0x02
  78 #  define SIL164_DETECT_RECEIVER_STAT           0x04
  79 #  define SIL164_DETECT_INTR_MODE_RECEIVER      0x00
  80 #  define SIL164_DETECT_INTR_MODE_HOTPLUG       0x08
  81 #  define SIL164_DETECT_OUT_MODE_HIGH           0x00
  82 #  define SIL164_DETECT_OUT_MODE_INTR           0x10
  83 #  define SIL164_DETECT_OUT_MODE_RECEIVER       0x20
  84 #  define SIL164_DETECT_OUT_MODE_HOTPLUG        0x30
  85 #  define SIL164_DETECT_VSWING_STAT             0x80
  86 #define SIL164_CONTROL1                         0xa
  87 #  define SIL164_CONTROL1_DESKEW_ENABLE         0x10
  88 #  define SIL164_CONTROL1_DESKEW_INCR_SHIFT     5
  89 #define SIL164_GPIO                             0xb
  90 #define SIL164_CONTROL2                         0xc
  91 #  define SIL164_CONTROL2_FILTER_ENABLE         0x01
  92 #  define SIL164_CONTROL2_FILTER_SETTING_SHIFT  1
  93 #  define SIL164_CONTROL2_DUALLINK_MASTER       0x40
  94 #  define SIL164_CONTROL2_SYNC_CONT             0x80
  95 #define SIL164_DUALLINK                         0xd
  96 #  define SIL164_DUALLINK_ENABLE                0x10
  97 #  define SIL164_DUALLINK_SKEW_SHIFT            5
  98 #define SIL164_PLLZONE                          0xe
  99 #  define SIL164_PLLZONE_STAT                   0x08
 100 #  define SIL164_PLLZONE_FORCE_ON               0x10
 101 #  define SIL164_PLLZONE_FORCE_HIGH             0x20
 102 
 103 /* HW access functions */
 104 
 105 static void
 106 sil164_write(struct i2c_client *client, uint8_t addr, uint8_t val)
 107 {
 108         uint8_t buf[] = {addr, val};
 109         int ret;
 110 
 111         ret = i2c_master_send(client, buf, ARRAY_SIZE(buf));
 112         if (ret < 0)
 113                 sil164_err(client, "Error %d writing to subaddress 0x%x\n",
 114                            ret, addr);
 115 }
 116 
 117 static uint8_t
 118 sil164_read(struct i2c_client *client, uint8_t addr)
 119 {
 120         uint8_t val;
 121         int ret;
 122 
 123         ret = i2c_master_send(client, &addr, sizeof(addr));
 124         if (ret < 0)
 125                 goto fail;
 126 
 127         ret = i2c_master_recv(client, &val, sizeof(val));
 128         if (ret < 0)
 129                 goto fail;
 130 
 131         return val;
 132 
 133 fail:
 134         sil164_err(client, "Error %d reading from subaddress 0x%x\n",
 135                    ret, addr);
 136         return 0;
 137 }
 138 
 139 static void
 140 sil164_save_state(struct i2c_client *client, uint8_t *state)
 141 {
 142         int i;
 143 
 144         for (i = 0x8; i <= 0xe; i++)
 145                 state[i] = sil164_read(client, i);
 146 }
 147 
 148 static void
 149 sil164_restore_state(struct i2c_client *client, uint8_t *state)
 150 {
 151         int i;
 152 
 153         for (i = 0x8; i <= 0xe; i++)
 154                 sil164_write(client, i, state[i]);
 155 }
 156 
 157 static void
 158 sil164_set_power_state(struct i2c_client *client, bool on)
 159 {
 160         uint8_t control0 = sil164_read(client, SIL164_CONTROL0);
 161 
 162         if (on)
 163                 control0 |= SIL164_CONTROL0_POWER_ON;
 164         else
 165                 control0 &= ~SIL164_CONTROL0_POWER_ON;
 166 
 167         sil164_write(client, SIL164_CONTROL0, control0);
 168 }
 169 
 170 static void
 171 sil164_init_state(struct i2c_client *client,
 172                   struct sil164_encoder_params *config,
 173                   bool duallink)
 174 {
 175         sil164_write(client, SIL164_CONTROL0,
 176                      SIL164_CONTROL0_HSYNC_ON |
 177                      SIL164_CONTROL0_VSYNC_ON |
 178                      (config->input_edge ? SIL164_CONTROL0_EDGE_RISING : 0) |
 179                      (config->input_width ? SIL164_CONTROL0_INPUT_24BIT : 0) |
 180                      (config->input_dual ? SIL164_CONTROL0_DUAL_EDGE : 0));
 181 
 182         sil164_write(client, SIL164_DETECT,
 183                      SIL164_DETECT_INTR_STAT |
 184                      SIL164_DETECT_OUT_MODE_RECEIVER);
 185 
 186         sil164_write(client, SIL164_CONTROL1,
 187                      (config->input_skew ? SIL164_CONTROL1_DESKEW_ENABLE : 0) |
 188                      (((config->input_skew + 4) & 0x7)
 189                       << SIL164_CONTROL1_DESKEW_INCR_SHIFT));
 190 
 191         sil164_write(client, SIL164_CONTROL2,
 192                      SIL164_CONTROL2_SYNC_CONT |
 193                      (config->pll_filter ? 0 : SIL164_CONTROL2_FILTER_ENABLE) |
 194                      (4 << SIL164_CONTROL2_FILTER_SETTING_SHIFT));
 195 
 196         sil164_write(client, SIL164_PLLZONE, 0);
 197 
 198         if (duallink)
 199                 sil164_write(client, SIL164_DUALLINK,
 200                              SIL164_DUALLINK_ENABLE |
 201                              (((config->duallink_skew + 4) & 0x7)
 202                               << SIL164_DUALLINK_SKEW_SHIFT));
 203         else
 204                 sil164_write(client, SIL164_DUALLINK, 0);
 205 }
 206 
 207 /* DRM encoder functions */
 208 
 209 static void
 210 sil164_encoder_set_config(struct drm_encoder *encoder, void *params)
 211 {
 212         struct sil164_priv *priv = to_sil164_priv(encoder);
 213 
 214         priv->config = *(struct sil164_encoder_params *)params;
 215 }
 216 
 217 static void
 218 sil164_encoder_dpms(struct drm_encoder *encoder, int mode)
 219 {
 220         struct sil164_priv *priv = to_sil164_priv(encoder);
 221         bool on = (mode == DRM_MODE_DPMS_ON);
 222         bool duallink = (on && encoder->crtc->mode.clock > 165000);
 223 
 224         sil164_set_power_state(drm_i2c_encoder_get_client(encoder), on);
 225 
 226         if (priv->duallink_slave)
 227                 sil164_set_power_state(priv->duallink_slave, duallink);
 228 }
 229 
 230 static void
 231 sil164_encoder_save(struct drm_encoder *encoder)
 232 {
 233         struct sil164_priv *priv = to_sil164_priv(encoder);
 234 
 235         sil164_save_state(drm_i2c_encoder_get_client(encoder),
 236                           priv->saved_state);
 237 
 238         if (priv->duallink_slave)
 239                 sil164_save_state(priv->duallink_slave,
 240                                   priv->saved_slave_state);
 241 }
 242 
 243 static void
 244 sil164_encoder_restore(struct drm_encoder *encoder)
 245 {
 246         struct sil164_priv *priv = to_sil164_priv(encoder);
 247 
 248         sil164_restore_state(drm_i2c_encoder_get_client(encoder),
 249                              priv->saved_state);
 250 
 251         if (priv->duallink_slave)
 252                 sil164_restore_state(priv->duallink_slave,
 253                                      priv->saved_slave_state);
 254 }
 255 
 256 static int
 257 sil164_encoder_mode_valid(struct drm_encoder *encoder,
 258                           struct drm_display_mode *mode)
 259 {
 260         struct sil164_priv *priv = to_sil164_priv(encoder);
 261 
 262         if (mode->clock < 32000)
 263                 return MODE_CLOCK_LOW;
 264 
 265         if (mode->clock > 330000 ||
 266             (mode->clock > 165000 && !priv->duallink_slave))
 267                 return MODE_CLOCK_HIGH;
 268 
 269         return MODE_OK;
 270 }
 271 
 272 static void
 273 sil164_encoder_mode_set(struct drm_encoder *encoder,
 274                         struct drm_display_mode *mode,
 275                         struct drm_display_mode *adjusted_mode)
 276 {
 277         struct sil164_priv *priv = to_sil164_priv(encoder);
 278         bool duallink = adjusted_mode->clock > 165000;
 279 
 280         sil164_init_state(drm_i2c_encoder_get_client(encoder),
 281                           &priv->config, duallink);
 282 
 283         if (priv->duallink_slave)
 284                 sil164_init_state(priv->duallink_slave,
 285                                   &priv->config, duallink);
 286 
 287         sil164_encoder_dpms(encoder, DRM_MODE_DPMS_ON);
 288 }
 289 
 290 static enum drm_connector_status
 291 sil164_encoder_detect(struct drm_encoder *encoder,
 292                       struct drm_connector *connector)
 293 {
 294         struct i2c_client *client = drm_i2c_encoder_get_client(encoder);
 295 
 296         if (sil164_read(client, SIL164_DETECT) & SIL164_DETECT_HOTPLUG_STAT)
 297                 return connector_status_connected;
 298         else
 299                 return connector_status_disconnected;
 300 }
 301 
 302 static int
 303 sil164_encoder_get_modes(struct drm_encoder *encoder,
 304                          struct drm_connector *connector)
 305 {
 306         return 0;
 307 }
 308 
 309 static int
 310 sil164_encoder_create_resources(struct drm_encoder *encoder,
 311                                 struct drm_connector *connector)
 312 {
 313         return 0;
 314 }
 315 
 316 static int
 317 sil164_encoder_set_property(struct drm_encoder *encoder,
 318                             struct drm_connector *connector,
 319                             struct drm_property *property,
 320                             uint64_t val)
 321 {
 322         return 0;
 323 }
 324 
 325 static void
 326 sil164_encoder_destroy(struct drm_encoder *encoder)
 327 {
 328         struct sil164_priv *priv = to_sil164_priv(encoder);
 329 
 330         i2c_unregister_device(priv->duallink_slave);
 331 
 332         kfree(priv);
 333         drm_i2c_encoder_destroy(encoder);
 334 }
 335 
 336 static const struct drm_encoder_slave_funcs sil164_encoder_funcs = {
 337         .set_config = sil164_encoder_set_config,
 338         .destroy = sil164_encoder_destroy,
 339         .dpms = sil164_encoder_dpms,
 340         .save = sil164_encoder_save,
 341         .restore = sil164_encoder_restore,
 342         .mode_valid = sil164_encoder_mode_valid,
 343         .mode_set = sil164_encoder_mode_set,
 344         .detect = sil164_encoder_detect,
 345         .get_modes = sil164_encoder_get_modes,
 346         .create_resources = sil164_encoder_create_resources,
 347         .set_property = sil164_encoder_set_property,
 348 };
 349 
 350 /* I2C driver functions */
 351 
 352 static int
 353 sil164_probe(struct i2c_client *client, const struct i2c_device_id *id)
 354 {
 355         int vendor = sil164_read(client, SIL164_VENDOR_HI) << 8 |
 356                 sil164_read(client, SIL164_VENDOR_LO);
 357         int device = sil164_read(client, SIL164_DEVICE_HI) << 8 |
 358                 sil164_read(client, SIL164_DEVICE_LO);
 359         int rev = sil164_read(client, SIL164_REVISION);
 360 
 361         if (vendor != 0x1 || device != 0x6) {
 362                 sil164_dbg(client, "Unknown device %x:%x.%x\n",
 363                            vendor, device, rev);
 364                 return -ENODEV;
 365         }
 366 
 367         sil164_info(client, "Detected device %x:%x.%x\n",
 368                     vendor, device, rev);
 369 
 370         return 0;
 371 }
 372 
 373 static int
 374 sil164_remove(struct i2c_client *client)
 375 {
 376         return 0;
 377 }
 378 
 379 static struct i2c_client *
 380 sil164_detect_slave(struct i2c_client *client)
 381 {
 382         struct i2c_adapter *adap = client->adapter;
 383         struct i2c_msg msg = {
 384                 .addr = SIL164_I2C_ADDR_SLAVE,
 385                 .len = 0,
 386         };
 387         const struct i2c_board_info info = {
 388                 I2C_BOARD_INFO("sil164", SIL164_I2C_ADDR_SLAVE)
 389         };
 390 
 391         if (i2c_transfer(adap, &msg, 1) != 1) {
 392                 sil164_dbg(adap, "No dual-link slave found.");
 393                 return NULL;
 394         }
 395 
 396         return i2c_new_device(adap, &info);
 397 }
 398 
 399 static int
 400 sil164_encoder_init(struct i2c_client *client,
 401                     struct drm_device *dev,
 402                     struct drm_encoder_slave *encoder)
 403 {
 404         struct sil164_priv *priv;
 405 
 406         priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 407         if (!priv)
 408                 return -ENOMEM;
 409 
 410         encoder->slave_priv = priv;
 411         encoder->slave_funcs = &sil164_encoder_funcs;
 412 
 413         priv->duallink_slave = sil164_detect_slave(client);
 414 
 415         return 0;
 416 }
 417 
 418 static const struct i2c_device_id sil164_ids[] = {
 419         { "sil164", 0 },
 420         { }
 421 };
 422 MODULE_DEVICE_TABLE(i2c, sil164_ids);
 423 
 424 static struct drm_i2c_encoder_driver sil164_driver = {
 425         .i2c_driver = {
 426                 .probe = sil164_probe,
 427                 .remove = sil164_remove,
 428                 .driver = {
 429                         .name = "sil164",
 430                 },
 431                 .id_table = sil164_ids,
 432         },
 433         .encoder_init = sil164_encoder_init,
 434 };
 435 
 436 /* Module initialization */
 437 
 438 static int __init
 439 sil164_init(void)
 440 {
 441         return drm_i2c_encoder_register(THIS_MODULE, &sil164_driver);
 442 }
 443 
 444 static void __exit
 445 sil164_exit(void)
 446 {
 447         drm_i2c_encoder_unregister(&sil164_driver);
 448 }
 449 
 450 MODULE_AUTHOR("Francisco Jerez <currojerez@riseup.net>");
 451 MODULE_DESCRIPTION("Silicon Image sil164 TMDS transmitter driver");
 452 MODULE_LICENSE("GPL and additional rights");
 453 
 454 module_init(sil164_init);
 455 module_exit(sil164_exit);

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