Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright (C) 2010 Francisco Jerez.
0003  * All Rights Reserved.
0004  *
0005  * Permission is hereby granted, free of charge, to any person obtaining
0006  * a copy of this software and associated documentation files (the
0007  * "Software"), to deal in the Software without restriction, including
0008  * without limitation the rights to use, copy, modify, merge, publish,
0009  * distribute, sublicense, and/or sell copies of the Software, and to
0010  * permit persons to whom the Software is furnished to do so, subject to
0011  * the following conditions:
0012  *
0013  * The above copyright notice and this permission notice (including the
0014  * next paragraph) shall be included in all copies or substantial
0015  * portions of the Software.
0016  *
0017  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
0018  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
0019  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
0020  * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
0021  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
0022  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
0023  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
0024  *
0025  */
0026 
0027 #include <linux/module.h>
0028 
0029 #include <drm/drm_drv.h>
0030 #include <drm/drm_encoder_slave.h>
0031 #include <drm/drm_print.h>
0032 #include <drm/drm_probe_helper.h>
0033 #include <drm/i2c/sil164.h>
0034 
0035 struct sil164_priv {
0036     struct sil164_encoder_params config;
0037     struct i2c_client *duallink_slave;
0038 
0039     uint8_t saved_state[0x10];
0040     uint8_t saved_slave_state[0x10];
0041 };
0042 
0043 #define to_sil164_priv(x) \
0044     ((struct sil164_priv *)to_encoder_slave(x)->slave_priv)
0045 
0046 #define sil164_dbg(client, format, ...) do {                \
0047         if (drm_debug_enabled(DRM_UT_KMS))          \
0048             dev_printk(KERN_DEBUG, &client->dev,        \
0049                    "%s: " format, __func__, ## __VA_ARGS__); \
0050     } while (0)
0051 #define sil164_info(client, format, ...)        \
0052     dev_info(&client->dev, format, __VA_ARGS__)
0053 #define sil164_err(client, format, ...)         \
0054     dev_err(&client->dev, format, __VA_ARGS__)
0055 
0056 #define SIL164_I2C_ADDR_MASTER          0x38
0057 #define SIL164_I2C_ADDR_SLAVE           0x39
0058 
0059 /* HW register definitions */
0060 
0061 #define SIL164_VENDOR_LO            0x0
0062 #define SIL164_VENDOR_HI            0x1
0063 #define SIL164_DEVICE_LO            0x2
0064 #define SIL164_DEVICE_HI            0x3
0065 #define SIL164_REVISION             0x4
0066 #define SIL164_FREQ_MIN             0x6
0067 #define SIL164_FREQ_MAX             0x7
0068 #define SIL164_CONTROL0             0x8
0069 #  define SIL164_CONTROL0_POWER_ON      0x01
0070 #  define SIL164_CONTROL0_EDGE_RISING       0x02
0071 #  define SIL164_CONTROL0_INPUT_24BIT       0x04
0072 #  define SIL164_CONTROL0_DUAL_EDGE     0x08
0073 #  define SIL164_CONTROL0_HSYNC_ON      0x10
0074 #  define SIL164_CONTROL0_VSYNC_ON      0x20
0075 #define SIL164_DETECT               0x9
0076 #  define SIL164_DETECT_INTR_STAT       0x01
0077 #  define SIL164_DETECT_HOTPLUG_STAT        0x02
0078 #  define SIL164_DETECT_RECEIVER_STAT       0x04
0079 #  define SIL164_DETECT_INTR_MODE_RECEIVER  0x00
0080 #  define SIL164_DETECT_INTR_MODE_HOTPLUG   0x08
0081 #  define SIL164_DETECT_OUT_MODE_HIGH       0x00
0082 #  define SIL164_DETECT_OUT_MODE_INTR       0x10
0083 #  define SIL164_DETECT_OUT_MODE_RECEIVER   0x20
0084 #  define SIL164_DETECT_OUT_MODE_HOTPLUG    0x30
0085 #  define SIL164_DETECT_VSWING_STAT     0x80
0086 #define SIL164_CONTROL1             0xa
0087 #  define SIL164_CONTROL1_DESKEW_ENABLE     0x10
0088 #  define SIL164_CONTROL1_DESKEW_INCR_SHIFT 5
0089 #define SIL164_GPIO             0xb
0090 #define SIL164_CONTROL2             0xc
0091 #  define SIL164_CONTROL2_FILTER_ENABLE     0x01
0092 #  define SIL164_CONTROL2_FILTER_SETTING_SHIFT  1
0093 #  define SIL164_CONTROL2_DUALLINK_MASTER   0x40
0094 #  define SIL164_CONTROL2_SYNC_CONT     0x80
0095 #define SIL164_DUALLINK             0xd
0096 #  define SIL164_DUALLINK_ENABLE        0x10
0097 #  define SIL164_DUALLINK_SKEW_SHIFT        5
0098 #define SIL164_PLLZONE              0xe
0099 #  define SIL164_PLLZONE_STAT           0x08
0100 #  define SIL164_PLLZONE_FORCE_ON       0x10
0101 #  define SIL164_PLLZONE_FORCE_HIGH     0x20
0102 
0103 /* HW access functions */
0104 
0105 static void
0106 sil164_write(struct i2c_client *client, uint8_t addr, uint8_t val)
0107 {
0108     uint8_t buf[] = {addr, val};
0109     int ret;
0110 
0111     ret = i2c_master_send(client, buf, ARRAY_SIZE(buf));
0112     if (ret < 0)
0113         sil164_err(client, "Error %d writing to subaddress 0x%x\n",
0114                ret, addr);
0115 }
0116 
0117 static uint8_t
0118 sil164_read(struct i2c_client *client, uint8_t addr)
0119 {
0120     uint8_t val;
0121     int ret;
0122 
0123     ret = i2c_master_send(client, &addr, sizeof(addr));
0124     if (ret < 0)
0125         goto fail;
0126 
0127     ret = i2c_master_recv(client, &val, sizeof(val));
0128     if (ret < 0)
0129         goto fail;
0130 
0131     return val;
0132 
0133 fail:
0134     sil164_err(client, "Error %d reading from subaddress 0x%x\n",
0135            ret, addr);
0136     return 0;
0137 }
0138 
0139 static void
0140 sil164_save_state(struct i2c_client *client, uint8_t *state)
0141 {
0142     int i;
0143 
0144     for (i = 0x8; i <= 0xe; i++)
0145         state[i] = sil164_read(client, i);
0146 }
0147 
0148 static void
0149 sil164_restore_state(struct i2c_client *client, uint8_t *state)
0150 {
0151     int i;
0152 
0153     for (i = 0x8; i <= 0xe; i++)
0154         sil164_write(client, i, state[i]);
0155 }
0156 
0157 static void
0158 sil164_set_power_state(struct i2c_client *client, bool on)
0159 {
0160     uint8_t control0 = sil164_read(client, SIL164_CONTROL0);
0161 
0162     if (on)
0163         control0 |= SIL164_CONTROL0_POWER_ON;
0164     else
0165         control0 &= ~SIL164_CONTROL0_POWER_ON;
0166 
0167     sil164_write(client, SIL164_CONTROL0, control0);
0168 }
0169 
0170 static void
0171 sil164_init_state(struct i2c_client *client,
0172           struct sil164_encoder_params *config,
0173           bool duallink)
0174 {
0175     sil164_write(client, SIL164_CONTROL0,
0176              SIL164_CONTROL0_HSYNC_ON |
0177              SIL164_CONTROL0_VSYNC_ON |
0178              (config->input_edge ? SIL164_CONTROL0_EDGE_RISING : 0) |
0179              (config->input_width ? SIL164_CONTROL0_INPUT_24BIT : 0) |
0180              (config->input_dual ? SIL164_CONTROL0_DUAL_EDGE : 0));
0181 
0182     sil164_write(client, SIL164_DETECT,
0183              SIL164_DETECT_INTR_STAT |
0184              SIL164_DETECT_OUT_MODE_RECEIVER);
0185 
0186     sil164_write(client, SIL164_CONTROL1,
0187              (config->input_skew ? SIL164_CONTROL1_DESKEW_ENABLE : 0) |
0188              (((config->input_skew + 4) & 0x7)
0189               << SIL164_CONTROL1_DESKEW_INCR_SHIFT));
0190 
0191     sil164_write(client, SIL164_CONTROL2,
0192              SIL164_CONTROL2_SYNC_CONT |
0193              (config->pll_filter ? 0 : SIL164_CONTROL2_FILTER_ENABLE) |
0194              (4 << SIL164_CONTROL2_FILTER_SETTING_SHIFT));
0195 
0196     sil164_write(client, SIL164_PLLZONE, 0);
0197 
0198     if (duallink)
0199         sil164_write(client, SIL164_DUALLINK,
0200                  SIL164_DUALLINK_ENABLE |
0201                  (((config->duallink_skew + 4) & 0x7)
0202                   << SIL164_DUALLINK_SKEW_SHIFT));
0203     else
0204         sil164_write(client, SIL164_DUALLINK, 0);
0205 }
0206 
0207 /* DRM encoder functions */
0208 
0209 static void
0210 sil164_encoder_set_config(struct drm_encoder *encoder, void *params)
0211 {
0212     struct sil164_priv *priv = to_sil164_priv(encoder);
0213 
0214     priv->config = *(struct sil164_encoder_params *)params;
0215 }
0216 
0217 static void
0218 sil164_encoder_dpms(struct drm_encoder *encoder, int mode)
0219 {
0220     struct sil164_priv *priv = to_sil164_priv(encoder);
0221     bool on = (mode == DRM_MODE_DPMS_ON);
0222     bool duallink = (on && encoder->crtc->mode.clock > 165000);
0223 
0224     sil164_set_power_state(drm_i2c_encoder_get_client(encoder), on);
0225 
0226     if (priv->duallink_slave)
0227         sil164_set_power_state(priv->duallink_slave, duallink);
0228 }
0229 
0230 static void
0231 sil164_encoder_save(struct drm_encoder *encoder)
0232 {
0233     struct sil164_priv *priv = to_sil164_priv(encoder);
0234 
0235     sil164_save_state(drm_i2c_encoder_get_client(encoder),
0236               priv->saved_state);
0237 
0238     if (priv->duallink_slave)
0239         sil164_save_state(priv->duallink_slave,
0240                   priv->saved_slave_state);
0241 }
0242 
0243 static void
0244 sil164_encoder_restore(struct drm_encoder *encoder)
0245 {
0246     struct sil164_priv *priv = to_sil164_priv(encoder);
0247 
0248     sil164_restore_state(drm_i2c_encoder_get_client(encoder),
0249                  priv->saved_state);
0250 
0251     if (priv->duallink_slave)
0252         sil164_restore_state(priv->duallink_slave,
0253                      priv->saved_slave_state);
0254 }
0255 
0256 static int
0257 sil164_encoder_mode_valid(struct drm_encoder *encoder,
0258               struct drm_display_mode *mode)
0259 {
0260     struct sil164_priv *priv = to_sil164_priv(encoder);
0261 
0262     if (mode->clock < 32000)
0263         return MODE_CLOCK_LOW;
0264 
0265     if (mode->clock > 330000 ||
0266         (mode->clock > 165000 && !priv->duallink_slave))
0267         return MODE_CLOCK_HIGH;
0268 
0269     return MODE_OK;
0270 }
0271 
0272 static void
0273 sil164_encoder_mode_set(struct drm_encoder *encoder,
0274             struct drm_display_mode *mode,
0275             struct drm_display_mode *adjusted_mode)
0276 {
0277     struct sil164_priv *priv = to_sil164_priv(encoder);
0278     bool duallink = adjusted_mode->clock > 165000;
0279 
0280     sil164_init_state(drm_i2c_encoder_get_client(encoder),
0281               &priv->config, duallink);
0282 
0283     if (priv->duallink_slave)
0284         sil164_init_state(priv->duallink_slave,
0285                   &priv->config, duallink);
0286 
0287     sil164_encoder_dpms(encoder, DRM_MODE_DPMS_ON);
0288 }
0289 
0290 static enum drm_connector_status
0291 sil164_encoder_detect(struct drm_encoder *encoder,
0292               struct drm_connector *connector)
0293 {
0294     struct i2c_client *client = drm_i2c_encoder_get_client(encoder);
0295 
0296     if (sil164_read(client, SIL164_DETECT) & SIL164_DETECT_HOTPLUG_STAT)
0297         return connector_status_connected;
0298     else
0299         return connector_status_disconnected;
0300 }
0301 
0302 static int
0303 sil164_encoder_get_modes(struct drm_encoder *encoder,
0304              struct drm_connector *connector)
0305 {
0306     return 0;
0307 }
0308 
0309 static int
0310 sil164_encoder_create_resources(struct drm_encoder *encoder,
0311                 struct drm_connector *connector)
0312 {
0313     return 0;
0314 }
0315 
0316 static int
0317 sil164_encoder_set_property(struct drm_encoder *encoder,
0318                 struct drm_connector *connector,
0319                 struct drm_property *property,
0320                 uint64_t val)
0321 {
0322     return 0;
0323 }
0324 
0325 static void
0326 sil164_encoder_destroy(struct drm_encoder *encoder)
0327 {
0328     struct sil164_priv *priv = to_sil164_priv(encoder);
0329 
0330     i2c_unregister_device(priv->duallink_slave);
0331 
0332     kfree(priv);
0333     drm_i2c_encoder_destroy(encoder);
0334 }
0335 
0336 static const struct drm_encoder_slave_funcs sil164_encoder_funcs = {
0337     .set_config = sil164_encoder_set_config,
0338     .destroy = sil164_encoder_destroy,
0339     .dpms = sil164_encoder_dpms,
0340     .save = sil164_encoder_save,
0341     .restore = sil164_encoder_restore,
0342     .mode_valid = sil164_encoder_mode_valid,
0343     .mode_set = sil164_encoder_mode_set,
0344     .detect = sil164_encoder_detect,
0345     .get_modes = sil164_encoder_get_modes,
0346     .create_resources = sil164_encoder_create_resources,
0347     .set_property = sil164_encoder_set_property,
0348 };
0349 
0350 /* I2C driver functions */
0351 
0352 static int
0353 sil164_probe(struct i2c_client *client, const struct i2c_device_id *id)
0354 {
0355     int vendor = sil164_read(client, SIL164_VENDOR_HI) << 8 |
0356         sil164_read(client, SIL164_VENDOR_LO);
0357     int device = sil164_read(client, SIL164_DEVICE_HI) << 8 |
0358         sil164_read(client, SIL164_DEVICE_LO);
0359     int rev = sil164_read(client, SIL164_REVISION);
0360 
0361     if (vendor != 0x1 || device != 0x6) {
0362         sil164_dbg(client, "Unknown device %x:%x.%x\n",
0363                vendor, device, rev);
0364         return -ENODEV;
0365     }
0366 
0367     sil164_info(client, "Detected device %x:%x.%x\n",
0368             vendor, device, rev);
0369 
0370     return 0;
0371 }
0372 
0373 static int
0374 sil164_remove(struct i2c_client *client)
0375 {
0376     return 0;
0377 }
0378 
0379 static struct i2c_client *
0380 sil164_detect_slave(struct i2c_client *client)
0381 {
0382     struct i2c_adapter *adap = client->adapter;
0383     struct i2c_msg msg = {
0384         .addr = SIL164_I2C_ADDR_SLAVE,
0385         .len = 0,
0386     };
0387     const struct i2c_board_info info = {
0388         I2C_BOARD_INFO("sil164", SIL164_I2C_ADDR_SLAVE)
0389     };
0390 
0391     if (i2c_transfer(adap, &msg, 1) != 1) {
0392         sil164_dbg(adap, "No dual-link slave found.");
0393         return NULL;
0394     }
0395 
0396     return i2c_new_client_device(adap, &info);
0397 }
0398 
0399 static int
0400 sil164_encoder_init(struct i2c_client *client,
0401             struct drm_device *dev,
0402             struct drm_encoder_slave *encoder)
0403 {
0404     struct sil164_priv *priv;
0405     struct i2c_client *slave_client;
0406 
0407     priv = kzalloc(sizeof(*priv), GFP_KERNEL);
0408     if (!priv)
0409         return -ENOMEM;
0410 
0411     encoder->slave_priv = priv;
0412     encoder->slave_funcs = &sil164_encoder_funcs;
0413 
0414     slave_client = sil164_detect_slave(client);
0415     if (!IS_ERR(slave_client))
0416         priv->duallink_slave = slave_client;
0417 
0418     return 0;
0419 }
0420 
0421 static const struct i2c_device_id sil164_ids[] = {
0422     { "sil164", 0 },
0423     { }
0424 };
0425 MODULE_DEVICE_TABLE(i2c, sil164_ids);
0426 
0427 static struct drm_i2c_encoder_driver sil164_driver = {
0428     .i2c_driver = {
0429         .probe = sil164_probe,
0430         .remove = sil164_remove,
0431         .driver = {
0432             .name = "sil164",
0433         },
0434         .id_table = sil164_ids,
0435     },
0436     .encoder_init = sil164_encoder_init,
0437 };
0438 
0439 /* Module initialization */
0440 
0441 static int __init
0442 sil164_init(void)
0443 {
0444     return drm_i2c_encoder_register(THIS_MODULE, &sil164_driver);
0445 }
0446 
0447 static void __exit
0448 sil164_exit(void)
0449 {
0450     drm_i2c_encoder_unregister(&sil164_driver);
0451 }
0452 
0453 MODULE_AUTHOR("Francisco Jerez <currojerez@riseup.net>");
0454 MODULE_DESCRIPTION("Silicon Image sil164 TMDS transmitter driver");
0455 MODULE_LICENSE("GPL and additional rights");
0456 
0457 module_init(sil164_init);
0458 module_exit(sil164_exit);