[media] v4l: s5p-tv: hdmiphy: add support for per-platform variants
authorTomasz Stanislawski <t.stanislaws@samsung.com>
Fri, 3 Feb 2012 17:00:11 +0000 (14:00 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Sun, 20 May 2012 12:01:19 +0000 (09:01 -0300)
Adds selection of HDMIPHY configuration tables basing on both preset
and platform variant.

Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/video/s5p-tv/hdmiphy_drv.c

index 0afef77747e593e0c7e421a248633e34cc6c57b9..f67b386318014c34dff3fdc13c9aa8815eaf1d13 100644 (file)
@@ -26,53 +26,188 @@ MODULE_DESCRIPTION("Samsung HDMI Physical interface driver");
 MODULE_LICENSE("GPL");
 
 struct hdmiphy_conf {
-       u32 preset;
+       unsigned long pixclk;
        const u8 *data;
 };
 
-static const u8 hdmiphy_conf27[32] = {
-       0x01, 0x05, 0x00, 0xD8, 0x10, 0x1C, 0x30, 0x40,
-       0x6B, 0x10, 0x02, 0x51, 0xDf, 0xF2, 0x54, 0x87,
-       0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
-       0x22, 0x40, 0xe3, 0x26, 0x00, 0x00, 0x00, 0x00,
+struct hdmiphy_ctx {
+       struct v4l2_subdev sd;
+       const struct hdmiphy_conf *conf_tab;
 };
 
-static const u8 hdmiphy_conf74_175[32] = {
-       0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xef, 0x5B,
-       0x6D, 0x10, 0x01, 0x51, 0xef, 0xF3, 0x54, 0xb9,
-       0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
-       0x22, 0x40, 0xa5, 0x26, 0x01, 0x00, 0x00, 0x00,
+static const struct hdmiphy_conf hdmiphy_conf_s5pv210[] = {
+       { .pixclk = 27000000, .data = (u8 [32]) {
+               0x01, 0x05, 0x00, 0xD8, 0x10, 0x1C, 0x30, 0x40,
+               0x6B, 0x10, 0x02, 0x52, 0xDF, 0xF2, 0x54, 0x87,
+               0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
+               0x22, 0x40, 0xE3, 0x26, 0x00, 0x00, 0x00, 0x00, }
+       },
+       { .pixclk = 27027000, .data = (u8 [32]) {
+               0x01, 0x05, 0x00, 0xD4, 0x10, 0x9C, 0x09, 0x64,
+               0x6B, 0x10, 0x02, 0x52, 0xDF, 0xF2, 0x54, 0x87,
+               0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
+               0x22, 0x40, 0xE2, 0x26, 0x00, 0x00, 0x00, 0x00, }
+       },
+       { .pixclk = 74176000, .data = (u8 [32]) {
+               0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xEF, 0x5B,
+               0x6D, 0x10, 0x01, 0x52, 0xEF, 0xF3, 0x54, 0xB9,
+               0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
+               0x22, 0x40, 0xA5, 0x26, 0x01, 0x00, 0x00, 0x00, }
+       },
+       { .pixclk = 74250000, .data = (u8 [32]) {
+               0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xF8, 0x40,
+               0x6A, 0x10, 0x01, 0x52, 0xFF, 0xF1, 0x54, 0xBA,
+               0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xE0,
+               0x22, 0x40, 0xA4, 0x26, 0x01, 0x00, 0x00, 0x00, }
+       },
+       { /* end marker */ }
 };
 
-static const u8 hdmiphy_conf74_25[32] = {
-       0x01, 0x05, 0x00, 0xd8, 0x10, 0x9c, 0xf8, 0x40,
-       0x6a, 0x10, 0x01, 0x51, 0xff, 0xf1, 0x54, 0xba,
-       0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xe0,
-       0x22, 0x40, 0xa4, 0x26, 0x01, 0x00, 0x00, 0x00,
+static const struct hdmiphy_conf hdmiphy_conf_exynos4210[] = {
+       { .pixclk = 27000000, .data = (u8 [32]) {
+               0x01, 0x05, 0x00, 0xD8, 0x10, 0x1C, 0x30, 0x40,
+               0x6B, 0x10, 0x02, 0x51, 0xDF, 0xF2, 0x54, 0x87,
+               0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
+               0x22, 0x40, 0xE3, 0x26, 0x00, 0x00, 0x00, 0x00, }
+       },
+       { .pixclk = 27027000, .data = (u8 [32]) {
+               0x01, 0x05, 0x00, 0xD4, 0x10, 0x9C, 0x09, 0x64,
+               0x6B, 0x10, 0x02, 0x51, 0xDF, 0xF2, 0x54, 0x87,
+               0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
+               0x22, 0x40, 0xE2, 0x26, 0x00, 0x00, 0x00, 0x00, }
+       },
+       { .pixclk = 74176000, .data = (u8 [32]) {
+               0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xEF, 0x5B,
+               0x6D, 0x10, 0x01, 0x51, 0xEF, 0xF3, 0x54, 0xB9,
+               0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
+               0x22, 0x40, 0xA5, 0x26, 0x01, 0x00, 0x00, 0x00, }
+       },
+       { .pixclk = 74250000, .data = (u8 [32]) {
+               0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xF8, 0x40,
+               0x6A, 0x10, 0x01, 0x51, 0xFF, 0xF1, 0x54, 0xBA,
+               0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xE0,
+               0x22, 0x40, 0xA4, 0x26, 0x01, 0x00, 0x00, 0x00, }
+       },
+       { .pixclk = 148352000, .data = (u8 [32]) {
+               0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xEF, 0x5B,
+               0x6D, 0x18, 0x00, 0x51, 0xEF, 0xF3, 0x54, 0xB9,
+               0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
+               0x11, 0x40, 0xA5, 0x26, 0x02, 0x00, 0x00, 0x00, }
+       },
+       { .pixclk = 148500000, .data = (u8 [32]) {
+               0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xF8, 0x40,
+               0x6A, 0x18, 0x00, 0x51, 0xFF, 0xF1, 0x54, 0xBA,
+               0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xE0,
+               0x11, 0x40, 0xA4, 0x26, 0x02, 0x00, 0x00, 0x00, }
+       },
+       { /* end marker */ }
 };
 
-static const u8 hdmiphy_conf148_5[32] = {
-       0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xf8, 0x40,
-       0x6A, 0x18, 0x00, 0x51, 0xff, 0xF1, 0x54, 0xba,
-       0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xE0,
-       0x22, 0x40, 0xa4, 0x26, 0x02, 0x00, 0x00, 0x00,
+static const struct hdmiphy_conf hdmiphy_conf_exynos4212[] = {
+       { .pixclk = 27000000, .data = (u8 [32]) {
+               0x01, 0x11, 0x2D, 0x75, 0x00, 0x01, 0x00, 0x08,
+               0x82, 0x00, 0x0E, 0xD9, 0x45, 0xA0, 0x34, 0xC0,
+               0x0B, 0x80, 0x12, 0x87, 0x08, 0x24, 0x24, 0x71,
+               0x54, 0xE3, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00, }
+       },
+       { .pixclk = 27027000, .data = (u8 [32]) {
+               0x01, 0x91, 0x2D, 0x72, 0x00, 0x64, 0x12, 0x08,
+               0x43, 0x20, 0x0E, 0xD9, 0x45, 0xA0, 0x34, 0xC0,
+               0x0B, 0x80, 0x12, 0x87, 0x08, 0x24, 0x24, 0x71,
+               0x54, 0xE2, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00, }
+       },
+       { .pixclk = 74176000, .data = (u8 [32]) {
+               0x01, 0x91, 0x3E, 0x35, 0x00, 0x5B, 0xDE, 0x08,
+               0x82, 0x20, 0x73, 0xD9, 0x45, 0xA0, 0x34, 0xC0,
+               0x0B, 0x80, 0x12, 0x87, 0x08, 0x24, 0x24, 0x52,
+               0x54, 0xA5, 0x24, 0x01, 0x00, 0x00, 0x01, 0x00, }
+       },
+       { .pixclk = 74250000, .data = (u8 [32]) {
+               0x01, 0x91, 0x3E, 0x35, 0x00, 0x40, 0xF0, 0x08,
+               0x82, 0x20, 0x73, 0xD9, 0x45, 0xA0, 0x34, 0xC0,
+               0x0B, 0x80, 0x12, 0x87, 0x08, 0x24, 0x24, 0x52,
+               0x54, 0xA4, 0x24, 0x01, 0x00, 0x00, 0x01, 0x00, }
+       },
+       { .pixclk = 148500000, .data = (u8 [32]) {
+               0x01, 0x91, 0x3E, 0x15, 0x00, 0x40, 0xF0, 0x08,
+               0x82, 0x20, 0x73, 0xD9, 0x45, 0xA0, 0x34, 0xC0,
+               0x0B, 0x80, 0x12, 0x87, 0x08, 0x24, 0x24, 0xA4,
+               0x54, 0x4A, 0x25, 0x03, 0x00, 0x00, 0x01, 0x00, }
+       },
+       { /* end marker */ }
 };
 
-static const struct hdmiphy_conf hdmiphy_conf[] = {
-       { V4L2_DV_480P59_94, hdmiphy_conf27 },
-       { V4L2_DV_1080P30, hdmiphy_conf74_175 },
-       { V4L2_DV_720P59_94, hdmiphy_conf74_175 },
-       { V4L2_DV_720P60, hdmiphy_conf74_25 },
-       { V4L2_DV_1080P50, hdmiphy_conf148_5 },
-       { V4L2_DV_1080P60, hdmiphy_conf148_5 },
+static const struct hdmiphy_conf hdmiphy_conf_exynos4412[] = {
+       { .pixclk = 27000000, .data = (u8 [32]) {
+               0x01, 0x11, 0x2D, 0x75, 0x40, 0x01, 0x00, 0x08,
+               0x82, 0x00, 0x0E, 0xD9, 0x45, 0xA0, 0xAC, 0x80,
+               0x08, 0x80, 0x11, 0x84, 0x02, 0x22, 0x44, 0x86,
+               0x54, 0xE4, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00, }
+       },
+       { .pixclk = 27027000, .data = (u8 [32]) {
+               0x01, 0x91, 0x2D, 0x72, 0x40, 0x64, 0x12, 0x08,
+               0x43, 0x20, 0x0E, 0xD9, 0x45, 0xA0, 0xAC, 0x80,
+               0x08, 0x80, 0x11, 0x84, 0x02, 0x22, 0x44, 0x86,
+               0x54, 0xE3, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00, }
+       },
+       { .pixclk = 74176000, .data = (u8 [32]) {
+               0x01, 0x91, 0x1F, 0x10, 0x40, 0x5B, 0xEF, 0x08,
+               0x81, 0x20, 0xB9, 0xD8, 0x45, 0xA0, 0xAC, 0x80,
+               0x08, 0x80, 0x11, 0x84, 0x02, 0x22, 0x44, 0x86,
+               0x54, 0xA6, 0x24, 0x01, 0x00, 0x00, 0x01, 0x00, }
+       },
+       { .pixclk = 74250000, .data = (u8 [32]) {
+               0x01, 0x91, 0x1F, 0x10, 0x40, 0x40, 0xF8, 0x08,
+               0x81, 0x20, 0xBA, 0xD8, 0x45, 0xA0, 0xAC, 0x80,
+               0x08, 0x80, 0x11, 0x84, 0x02, 0x22, 0x44, 0x86,
+               0x54, 0xA5, 0x24, 0x01, 0x00, 0x00, 0x01, 0x00, }
+       },
+       { .pixclk = 148500000, .data = (u8 [32]) {
+               0x01, 0x91, 0x1F, 0x00, 0x40, 0x40, 0xF8, 0x08,
+               0x81, 0x20, 0xBA, 0xD8, 0x45, 0xA0, 0xAC, 0x80,
+               0x08, 0x80, 0x11, 0x84, 0x02, 0x22, 0x44, 0x86,
+               0x54, 0x4B, 0x25, 0x03, 0x00, 0x00, 0x01, 0x00, }
+       },
+       { /* end marker */ }
 };
 
-const u8 *hdmiphy_preset2conf(u32 preset)
+static inline struct hdmiphy_ctx *sd_to_ctx(struct v4l2_subdev *sd)
+{
+       return container_of(sd, struct hdmiphy_ctx, sd);
+}
+
+static unsigned long hdmiphy_preset_to_pixclk(u32 preset)
+{
+       static const unsigned long pixclk[] = {
+               [V4L2_DV_480P59_94] =  27000000,
+               [V4L2_DV_576P50]    =  27000000,
+               [V4L2_DV_720P59_94] =  74176000,
+               [V4L2_DV_720P50]    =  74250000,
+               [V4L2_DV_720P60]    =  74250000,
+               [V4L2_DV_1080P24]   =  74250000,
+               [V4L2_DV_1080P30]   =  74250000,
+               [V4L2_DV_1080I50]   =  74250000,
+               [V4L2_DV_1080I60]   =  74250000,
+               [V4L2_DV_1080P50]   = 148500000,
+               [V4L2_DV_1080P60]   = 148500000,
+       };
+       if (preset < ARRAY_SIZE(pixclk))
+               return pixclk[preset];
+       else
+               return 0;
+}
+
+static const u8 *hdmiphy_find_conf(u32 preset, const struct hdmiphy_conf *conf)
 {
-       int i;
-       for (i = 0; i < ARRAY_SIZE(hdmiphy_conf); ++i)
-               if (hdmiphy_conf[i].preset == preset)
-                       return hdmiphy_conf[i].data;
+       unsigned long pixclk;
+
+       pixclk = hdmiphy_preset_to_pixclk(preset);
+       if (!pixclk)
+               return NULL;
+
+       for (; conf->pixclk; ++conf)
+               if (conf->pixclk == pixclk)
+                       return conf->data;
        return NULL;
 }
 
@@ -88,11 +223,12 @@ static int hdmiphy_s_dv_preset(struct v4l2_subdev *sd,
        const u8 *data;
        u8 buffer[32];
        int ret;
+       struct hdmiphy_ctx *ctx = sd_to_ctx(sd);
        struct i2c_client *client = v4l2_get_subdevdata(sd);
        struct device *dev = &client->dev;
 
        dev_info(dev, "s_dv_preset(preset = %d)\n", preset->preset);
-       data = hdmiphy_preset2conf(preset->preset);
+       data = hdmiphy_find_conf(preset->preset, ctx->conf_tab);
        if (!data) {
                dev_err(dev, "format not supported\n");
                return -EINVAL;
@@ -146,21 +282,36 @@ static const struct v4l2_subdev_ops hdmiphy_ops = {
 static int __devinit hdmiphy_probe(struct i2c_client *client,
        const struct i2c_device_id *id)
 {
-       static struct v4l2_subdev sd;
+       struct hdmiphy_ctx *ctx;
+
+       ctx = kzalloc(sizeof *ctx, GFP_KERNEL);
+       if (!ctx)
+               return -ENOMEM;
+
+       ctx->conf_tab = (struct hdmiphy_conf *)id->driver_data;
+       v4l2_i2c_subdev_init(&ctx->sd, client, &hdmiphy_ops);
 
-       v4l2_i2c_subdev_init(&sd, client, &hdmiphy_ops);
        dev_info(&client->dev, "probe successful\n");
        return 0;
 }
 
 static int __devexit hdmiphy_remove(struct i2c_client *client)
 {
+       struct v4l2_subdev *sd = i2c_get_clientdata(client);
+       struct hdmiphy_ctx *ctx = sd_to_ctx(sd);
+
+       kfree(ctx);
        dev_info(&client->dev, "remove successful\n");
+
        return 0;
 }
 
 static const struct i2c_device_id hdmiphy_id[] = {
-       { "hdmiphy", 0 },
+       { "hdmiphy", (unsigned long)hdmiphy_conf_exynos4210 },
+       { "hdmiphy-s5pv210", (unsigned long)hdmiphy_conf_s5pv210 },
+       { "hdmiphy-exynos4210", (unsigned long)hdmiphy_conf_exynos4210 },
+       { "hdmiphy-exynos4212", (unsigned long)hdmiphy_conf_exynos4212 },
+       { "hdmiphy-exynos4412", (unsigned long)hdmiphy_conf_exynos4412 },
        { },
 };
 MODULE_DEVICE_TABLE(i2c, hdmiphy_id);