]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/gpu/drm/nouveau/nv04_tv.c
drm/nouveau: Add some generic I2C gadget detection code.
[mv-sheeva.git] / drivers / gpu / drm / nouveau / nv04_tv.c
index c4e3404337d4708e7b60c57e538908455f2ac235..8de1eef3594a5a0b3fbdd7763a06aa0b645e7daf 100644 (file)
 
 #include "i2c/ch7006.h"
 
-static struct {
-       struct i2c_board_info board_info;
-       struct drm_encoder_funcs funcs;
-       struct drm_encoder_helper_funcs hfuncs;
-       void *params;
-
-} nv04_tv_encoder_info[] = {
+static struct i2c_board_info nv04_tv_encoder_info[] = {
        {
-               .board_info = { I2C_BOARD_INFO("ch7006", 0x75) },
-               .params = &(struct ch7006_encoder_params) {
+               I2C_BOARD_INFO("ch7006", 0x75),
+               .platform_data = &(struct ch7006_encoder_params) {
                        CH7006_FORMAT_RGB24m12I, CH7006_CLOCK_MASTER,
                        0, 0, 0,
                        CH7006_SYNC_SLAVE, CH7006_SYNC_SEPARATED,
                        CH7006_POUT_3_3V, CH7006_ACTIVE_HSYNC
-               },
+               }
        },
+       { }
 };
 
-static bool probe_i2c_addr(struct i2c_adapter *adapter, int addr)
-{
-       struct i2c_msg msg = {
-               .addr = addr,
-               .len = 0,
-       };
-
-       return i2c_transfer(adapter, &msg, 1) == 1;
-}
-
 int nv04_tv_identify(struct drm_device *dev, int i2c_index)
 {
-       struct nouveau_i2c_chan *i2c;
-       bool was_locked;
-       int i, ret;
-
-       NV_TRACE(dev, "Probing TV encoders on I2C bus: %d\n", i2c_index);
-
-       i2c = nouveau_i2c_find(dev, i2c_index);
-       if (!i2c)
-               return -ENODEV;
-
-       was_locked = NVLockVgaCrtcs(dev, false);
-
-       for (i = 0; i < ARRAY_SIZE(nv04_tv_encoder_info); i++) {
-               if (probe_i2c_addr(&i2c->adapter,
-                                  nv04_tv_encoder_info[i].board_info.addr)) {
-                       ret = i;
-                       break;
-               }
-       }
-
-       if (i < ARRAY_SIZE(nv04_tv_encoder_info)) {
-               NV_TRACE(dev, "Detected TV encoder: %s\n",
-                        nv04_tv_encoder_info[i].board_info.type);
-
-       } else {
-               NV_TRACE(dev, "No TV encoders found.\n");
-               i = -ENODEV;
-       }
-
-       NVLockVgaCrtcs(dev, was_locked);
-       return i;
+       return nouveau_i2c_identify(dev, "TV encoder",
+                                   nv04_tv_encoder_info, i2c_index);
 }
 
+
 #define PLLSEL_TV_CRTC1_MASK                           \
        (NV_PRAMDAC_PLL_COEFF_SELECT_TV_VSCLK1          \
         | NV_PRAMDAC_PLL_COEFF_SELECT_TV_PCLK1)
@@ -214,30 +171,33 @@ static void nv04_tv_commit(struct drm_encoder *encoder)
 
 static void nv04_tv_destroy(struct drm_encoder *encoder)
 {
-       struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
-
        to_encoder_slave(encoder)->slave_funcs->destroy(encoder);
 
        drm_encoder_cleanup(encoder);
 
-       kfree(nv_encoder);
+       kfree(encoder->helper_private);
+       kfree(nouveau_encoder(encoder));
 }
 
-int nv04_tv_create(struct drm_device *dev, struct dcb_entry *entry)
+static const struct drm_encoder_funcs nv04_tv_funcs = {
+       .destroy = nv04_tv_destroy,
+};
+
+int
+nv04_tv_create(struct drm_connector *connector, struct dcb_entry *entry)
 {
        struct nouveau_encoder *nv_encoder;
        struct drm_encoder *encoder;
-       struct drm_nouveau_private *dev_priv = dev->dev_private;
-       struct i2c_adapter *adap;
-       struct drm_encoder_funcs *funcs = NULL;
-       struct drm_encoder_helper_funcs *hfuncs = NULL;
-       struct drm_encoder_slave_funcs *sfuncs = NULL;
-       int i2c_index = entry->i2c_index;
+       struct drm_device *dev = connector->dev;
+       struct drm_encoder_helper_funcs *hfuncs;
+       struct drm_encoder_slave_funcs *sfuncs;
+       struct nouveau_i2c_chan *i2c =
+               nouveau_i2c_find(dev, entry->i2c_index);
        int type, ret;
        bool was_locked;
 
        /* Ensure that we can talk to this encoder */
-       type = nv04_tv_identify(dev, i2c_index);
+       type = nv04_tv_identify(dev, entry->i2c_index);
        if (type < 0)
                return type;
 
@@ -246,41 +206,37 @@ int nv04_tv_create(struct drm_device *dev, struct dcb_entry *entry)
        if (!nv_encoder)
                return -ENOMEM;
 
+       hfuncs = kzalloc(sizeof(*hfuncs), GFP_KERNEL);
+       if (!hfuncs) {
+               ret = -ENOMEM;
+               goto fail_free;
+       }
+
        /* Initialize the common members */
        encoder = to_drm_encoder(nv_encoder);
 
-       funcs = &nv04_tv_encoder_info[type].funcs;
-       hfuncs = &nv04_tv_encoder_info[type].hfuncs;
-
-       drm_encoder_init(dev, encoder, funcs, DRM_MODE_ENCODER_TVDAC);
+       drm_encoder_init(dev, encoder, &nv04_tv_funcs, DRM_MODE_ENCODER_TVDAC);
        drm_encoder_helper_add(encoder, hfuncs);
 
        encoder->possible_crtcs = entry->heads;
        encoder->possible_clones = 0;
-
        nv_encoder->dcb = entry;
        nv_encoder->or = ffs(entry->or) - 1;
 
        /* Run the slave-specific initialization */
-       adap = &dev_priv->vbios.dcb.i2c[i2c_index].chan->adapter;
-
        was_locked = NVLockVgaCrtcs(dev, false);
 
-       ret = drm_i2c_encoder_init(encoder->dev, to_encoder_slave(encoder), adap,
-                                  &nv04_tv_encoder_info[type].board_info);
+       ret = drm_i2c_encoder_init(dev, to_encoder_slave(encoder),
+                                  &i2c->adapter, &nv04_tv_encoder_info[type]);
 
        NVLockVgaCrtcs(dev, was_locked);
 
        if (ret < 0)
-               goto fail;
+               goto fail_cleanup;
 
        /* Fill the function pointers */
        sfuncs = to_encoder_slave(encoder)->slave_funcs;
 
-       *funcs = (struct drm_encoder_funcs) {
-               .destroy = nv04_tv_destroy,
-       };
-
        *hfuncs = (struct drm_encoder_helper_funcs) {
                .dpms = nv04_tv_dpms,
                .save = sfuncs->save,
@@ -292,14 +248,17 @@ int nv04_tv_create(struct drm_device *dev, struct dcb_entry *entry)
                .detect = sfuncs->detect,
        };
 
-       /* Set the slave encoder configuration */
-       sfuncs->set_config(encoder, nv04_tv_encoder_info[type].params);
+       /* Attach it to the specified connector. */
+       sfuncs->set_config(encoder, nv04_tv_encoder_info[type].platform_data);
+       sfuncs->create_resources(encoder, connector);
+       drm_mode_connector_attach_encoder(connector, encoder);
 
        return 0;
 
-fail:
+fail_cleanup:
        drm_encoder_cleanup(encoder);
-
+       kfree(hfuncs);
+fail_free:
        kfree(nv_encoder);
        return ret;
 }