aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomasz Stanislawski <t.stanislaws@samsung.com>2012-02-03 12:00:11 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-05-20 08:01:19 -0400
commit2470ea3f7f14283efa2f427884efc6634e39f243 (patch)
tree8c2de08720978b9af5694bf05b6e7f0fbc20853a
parentc31e3c4b1e70ff6bdf0cf415be15c399c4742def (diff)
[media] v4l: s5p-tv: hdmiphy: add support for per-platform variants
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>
-rw-r--r--drivers/media/video/s5p-tv/hdmiphy_drv.c225
1 files changed, 188 insertions, 37 deletions
diff --git a/drivers/media/video/s5p-tv/hdmiphy_drv.c b/drivers/media/video/s5p-tv/hdmiphy_drv.c
index 0afef77747e..f67b3863180 100644
--- a/drivers/media/video/s5p-tv/hdmiphy_drv.c
+++ b/drivers/media/video/s5p-tv/hdmiphy_drv.c
@@ -26,53 +26,188 @@ MODULE_DESCRIPTION("Samsung HDMI Physical interface driver");
26MODULE_LICENSE("GPL"); 26MODULE_LICENSE("GPL");
27 27
28struct hdmiphy_conf { 28struct hdmiphy_conf {
29 u32 preset; 29 unsigned long pixclk;
30 const u8 *data; 30 const u8 *data;
31}; 31};
32 32
33static const u8 hdmiphy_conf27[32] = { 33struct hdmiphy_ctx {
34 0x01, 0x05, 0x00, 0xD8, 0x10, 0x1C, 0x30, 0x40, 34 struct v4l2_subdev sd;
35 0x6B, 0x10, 0x02, 0x51, 0xDf, 0xF2, 0x54, 0x87, 35 const struct hdmiphy_conf *conf_tab;
36 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
37 0x22, 0x40, 0xe3, 0x26, 0x00, 0x00, 0x00, 0x00,
38}; 36};
39 37
40static const u8 hdmiphy_conf74_175[32] = { 38static const struct hdmiphy_conf hdmiphy_conf_s5pv210[] = {
41 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xef, 0x5B, 39 { .pixclk = 27000000, .data = (u8 [32]) {
42 0x6D, 0x10, 0x01, 0x51, 0xef, 0xF3, 0x54, 0xb9, 40 0x01, 0x05, 0x00, 0xD8, 0x10, 0x1C, 0x30, 0x40,
43 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0, 41 0x6B, 0x10, 0x02, 0x52, 0xDF, 0xF2, 0x54, 0x87,
44 0x22, 0x40, 0xa5, 0x26, 0x01, 0x00, 0x00, 0x00, 42 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
43 0x22, 0x40, 0xE3, 0x26, 0x00, 0x00, 0x00, 0x00, }
44 },
45 { .pixclk = 27027000, .data = (u8 [32]) {
46 0x01, 0x05, 0x00, 0xD4, 0x10, 0x9C, 0x09, 0x64,
47 0x6B, 0x10, 0x02, 0x52, 0xDF, 0xF2, 0x54, 0x87,
48 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
49 0x22, 0x40, 0xE2, 0x26, 0x00, 0x00, 0x00, 0x00, }
50 },
51 { .pixclk = 74176000, .data = (u8 [32]) {
52 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xEF, 0x5B,
53 0x6D, 0x10, 0x01, 0x52, 0xEF, 0xF3, 0x54, 0xB9,
54 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
55 0x22, 0x40, 0xA5, 0x26, 0x01, 0x00, 0x00, 0x00, }
56 },
57 { .pixclk = 74250000, .data = (u8 [32]) {
58 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xF8, 0x40,
59 0x6A, 0x10, 0x01, 0x52, 0xFF, 0xF1, 0x54, 0xBA,
60 0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xE0,
61 0x22, 0x40, 0xA4, 0x26, 0x01, 0x00, 0x00, 0x00, }
62 },
63 { /* end marker */ }
45}; 64};
46 65
47static const u8 hdmiphy_conf74_25[32] = { 66static const struct hdmiphy_conf hdmiphy_conf_exynos4210[] = {
48 0x01, 0x05, 0x00, 0xd8, 0x10, 0x9c, 0xf8, 0x40, 67 { .pixclk = 27000000, .data = (u8 [32]) {
49 0x6a, 0x10, 0x01, 0x51, 0xff, 0xf1, 0x54, 0xba, 68 0x01, 0x05, 0x00, 0xD8, 0x10, 0x1C, 0x30, 0x40,
50 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xe0, 69 0x6B, 0x10, 0x02, 0x51, 0xDF, 0xF2, 0x54, 0x87,
51 0x22, 0x40, 0xa4, 0x26, 0x01, 0x00, 0x00, 0x00, 70 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
71 0x22, 0x40, 0xE3, 0x26, 0x00, 0x00, 0x00, 0x00, }
72 },
73 { .pixclk = 27027000, .data = (u8 [32]) {
74 0x01, 0x05, 0x00, 0xD4, 0x10, 0x9C, 0x09, 0x64,
75 0x6B, 0x10, 0x02, 0x51, 0xDF, 0xF2, 0x54, 0x87,
76 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
77 0x22, 0x40, 0xE2, 0x26, 0x00, 0x00, 0x00, 0x00, }
78 },
79 { .pixclk = 74176000, .data = (u8 [32]) {
80 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xEF, 0x5B,
81 0x6D, 0x10, 0x01, 0x51, 0xEF, 0xF3, 0x54, 0xB9,
82 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
83 0x22, 0x40, 0xA5, 0x26, 0x01, 0x00, 0x00, 0x00, }
84 },
85 { .pixclk = 74250000, .data = (u8 [32]) {
86 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xF8, 0x40,
87 0x6A, 0x10, 0x01, 0x51, 0xFF, 0xF1, 0x54, 0xBA,
88 0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xE0,
89 0x22, 0x40, 0xA4, 0x26, 0x01, 0x00, 0x00, 0x00, }
90 },
91 { .pixclk = 148352000, .data = (u8 [32]) {
92 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xEF, 0x5B,
93 0x6D, 0x18, 0x00, 0x51, 0xEF, 0xF3, 0x54, 0xB9,
94 0x84, 0x00, 0x30, 0x38, 0x00, 0x08, 0x10, 0xE0,
95 0x11, 0x40, 0xA5, 0x26, 0x02, 0x00, 0x00, 0x00, }
96 },
97 { .pixclk = 148500000, .data = (u8 [32]) {
98 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xF8, 0x40,
99 0x6A, 0x18, 0x00, 0x51, 0xFF, 0xF1, 0x54, 0xBA,
100 0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xE0,
101 0x11, 0x40, 0xA4, 0x26, 0x02, 0x00, 0x00, 0x00, }
102 },
103 { /* end marker */ }
52}; 104};
53 105
54static const u8 hdmiphy_conf148_5[32] = { 106static const struct hdmiphy_conf hdmiphy_conf_exynos4212[] = {
55 0x01, 0x05, 0x00, 0xD8, 0x10, 0x9C, 0xf8, 0x40, 107 { .pixclk = 27000000, .data = (u8 [32]) {
56 0x6A, 0x18, 0x00, 0x51, 0xff, 0xF1, 0x54, 0xba, 108 0x01, 0x11, 0x2D, 0x75, 0x00, 0x01, 0x00, 0x08,
57 0x84, 0x00, 0x10, 0x38, 0x00, 0x08, 0x10, 0xE0, 109 0x82, 0x00, 0x0E, 0xD9, 0x45, 0xA0, 0x34, 0xC0,
58 0x22, 0x40, 0xa4, 0x26, 0x02, 0x00, 0x00, 0x00, 110 0x0B, 0x80, 0x12, 0x87, 0x08, 0x24, 0x24, 0x71,
111 0x54, 0xE3, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00, }
112 },
113 { .pixclk = 27027000, .data = (u8 [32]) {
114 0x01, 0x91, 0x2D, 0x72, 0x00, 0x64, 0x12, 0x08,
115 0x43, 0x20, 0x0E, 0xD9, 0x45, 0xA0, 0x34, 0xC0,
116 0x0B, 0x80, 0x12, 0x87, 0x08, 0x24, 0x24, 0x71,
117 0x54, 0xE2, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00, }
118 },
119 { .pixclk = 74176000, .data = (u8 [32]) {
120 0x01, 0x91, 0x3E, 0x35, 0x00, 0x5B, 0xDE, 0x08,
121 0x82, 0x20, 0x73, 0xD9, 0x45, 0xA0, 0x34, 0xC0,
122 0x0B, 0x80, 0x12, 0x87, 0x08, 0x24, 0x24, 0x52,
123 0x54, 0xA5, 0x24, 0x01, 0x00, 0x00, 0x01, 0x00, }
124 },
125 { .pixclk = 74250000, .data = (u8 [32]) {
126 0x01, 0x91, 0x3E, 0x35, 0x00, 0x40, 0xF0, 0x08,
127 0x82, 0x20, 0x73, 0xD9, 0x45, 0xA0, 0x34, 0xC0,
128 0x0B, 0x80, 0x12, 0x87, 0x08, 0x24, 0x24, 0x52,
129 0x54, 0xA4, 0x24, 0x01, 0x00, 0x00, 0x01, 0x00, }
130 },
131 { .pixclk = 148500000, .data = (u8 [32]) {
132 0x01, 0x91, 0x3E, 0x15, 0x00, 0x40, 0xF0, 0x08,
133 0x82, 0x20, 0x73, 0xD9, 0x45, 0xA0, 0x34, 0xC0,
134 0x0B, 0x80, 0x12, 0x87, 0x08, 0x24, 0x24, 0xA4,
135 0x54, 0x4A, 0x25, 0x03, 0x00, 0x00, 0x01, 0x00, }
136 },
137 { /* end marker */ }
59}; 138};
60 139
61static const struct hdmiphy_conf hdmiphy_conf[] = { 140static const struct hdmiphy_conf hdmiphy_conf_exynos4412[] = {
62 { V4L2_DV_480P59_94, hdmiphy_conf27 }, 141 { .pixclk = 27000000, .data = (u8 [32]) {
63 { V4L2_DV_1080P30, hdmiphy_conf74_175 }, 142 0x01, 0x11, 0x2D, 0x75, 0x40, 0x01, 0x00, 0x08,
64 { V4L2_DV_720P59_94, hdmiphy_conf74_175 }, 143 0x82, 0x00, 0x0E, 0xD9, 0x45, 0xA0, 0xAC, 0x80,
65 { V4L2_DV_720P60, hdmiphy_conf74_25 }, 144 0x08, 0x80, 0x11, 0x84, 0x02, 0x22, 0x44, 0x86,
66 { V4L2_DV_1080P50, hdmiphy_conf148_5 }, 145 0x54, 0xE4, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00, }
67 { V4L2_DV_1080P60, hdmiphy_conf148_5 }, 146 },
147 { .pixclk = 27027000, .data = (u8 [32]) {
148 0x01, 0x91, 0x2D, 0x72, 0x40, 0x64, 0x12, 0x08,
149 0x43, 0x20, 0x0E, 0xD9, 0x45, 0xA0, 0xAC, 0x80,
150 0x08, 0x80, 0x11, 0x84, 0x02, 0x22, 0x44, 0x86,
151 0x54, 0xE3, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00, }
152 },
153 { .pixclk = 74176000, .data = (u8 [32]) {
154 0x01, 0x91, 0x1F, 0x10, 0x40, 0x5B, 0xEF, 0x08,
155 0x81, 0x20, 0xB9, 0xD8, 0x45, 0xA0, 0xAC, 0x80,
156 0x08, 0x80, 0x11, 0x84, 0x02, 0x22, 0x44, 0x86,
157 0x54, 0xA6, 0x24, 0x01, 0x00, 0x00, 0x01, 0x00, }
158 },
159 { .pixclk = 74250000, .data = (u8 [32]) {
160 0x01, 0x91, 0x1F, 0x10, 0x40, 0x40, 0xF8, 0x08,
161 0x81, 0x20, 0xBA, 0xD8, 0x45, 0xA0, 0xAC, 0x80,
162 0x08, 0x80, 0x11, 0x84, 0x02, 0x22, 0x44, 0x86,
163 0x54, 0xA5, 0x24, 0x01, 0x00, 0x00, 0x01, 0x00, }
164 },
165 { .pixclk = 148500000, .data = (u8 [32]) {
166 0x01, 0x91, 0x1F, 0x00, 0x40, 0x40, 0xF8, 0x08,
167 0x81, 0x20, 0xBA, 0xD8, 0x45, 0xA0, 0xAC, 0x80,
168 0x08, 0x80, 0x11, 0x84, 0x02, 0x22, 0x44, 0x86,
169 0x54, 0x4B, 0x25, 0x03, 0x00, 0x00, 0x01, 0x00, }
170 },
171 { /* end marker */ }
68}; 172};
69 173
70const u8 *hdmiphy_preset2conf(u32 preset) 174static inline struct hdmiphy_ctx *sd_to_ctx(struct v4l2_subdev *sd)
175{
176 return container_of(sd, struct hdmiphy_ctx, sd);
177}
178
179static unsigned long hdmiphy_preset_to_pixclk(u32 preset)
180{
181 static const unsigned long pixclk[] = {
182 [V4L2_DV_480P59_94] = 27000000,
183 [V4L2_DV_576P50] = 27000000,
184 [V4L2_DV_720P59_94] = 74176000,
185 [V4L2_DV_720P50] = 74250000,
186 [V4L2_DV_720P60] = 74250000,
187 [V4L2_DV_1080P24] = 74250000,
188 [V4L2_DV_1080P30] = 74250000,
189 [V4L2_DV_1080I50] = 74250000,
190 [V4L2_DV_1080I60] = 74250000,
191 [V4L2_DV_1080P50] = 148500000,
192 [V4L2_DV_1080P60] = 148500000,
193 };
194 if (preset < ARRAY_SIZE(pixclk))
195 return pixclk[preset];
196 else
197 return 0;
198}
199
200static const u8 *hdmiphy_find_conf(u32 preset, const struct hdmiphy_conf *conf)
71{ 201{
72 int i; 202 unsigned long pixclk;
73 for (i = 0; i < ARRAY_SIZE(hdmiphy_conf); ++i) 203
74 if (hdmiphy_conf[i].preset == preset) 204 pixclk = hdmiphy_preset_to_pixclk(preset);
75 return hdmiphy_conf[i].data; 205 if (!pixclk)
206 return NULL;
207
208 for (; conf->pixclk; ++conf)
209 if (conf->pixclk == pixclk)
210 return conf->data;
76 return NULL; 211 return NULL;
77} 212}
78 213
@@ -88,11 +223,12 @@ static int hdmiphy_s_dv_preset(struct v4l2_subdev *sd,
88 const u8 *data; 223 const u8 *data;
89 u8 buffer[32]; 224 u8 buffer[32];
90 int ret; 225 int ret;
226 struct hdmiphy_ctx *ctx = sd_to_ctx(sd);
91 struct i2c_client *client = v4l2_get_subdevdata(sd); 227 struct i2c_client *client = v4l2_get_subdevdata(sd);
92 struct device *dev = &client->dev; 228 struct device *dev = &client->dev;
93 229
94 dev_info(dev, "s_dv_preset(preset = %d)\n", preset->preset); 230 dev_info(dev, "s_dv_preset(preset = %d)\n", preset->preset);
95 data = hdmiphy_preset2conf(preset->preset); 231 data = hdmiphy_find_conf(preset->preset, ctx->conf_tab);
96 if (!data) { 232 if (!data) {
97 dev_err(dev, "format not supported\n"); 233 dev_err(dev, "format not supported\n");
98 return -EINVAL; 234 return -EINVAL;
@@ -146,21 +282,36 @@ static const struct v4l2_subdev_ops hdmiphy_ops = {
146static int __devinit hdmiphy_probe(struct i2c_client *client, 282static int __devinit hdmiphy_probe(struct i2c_client *client,
147 const struct i2c_device_id *id) 283 const struct i2c_device_id *id)
148{ 284{
149 static struct v4l2_subdev sd; 285 struct hdmiphy_ctx *ctx;
286
287 ctx = kzalloc(sizeof *ctx, GFP_KERNEL);
288 if (!ctx)
289 return -ENOMEM;
290
291 ctx->conf_tab = (struct hdmiphy_conf *)id->driver_data;
292 v4l2_i2c_subdev_init(&ctx->sd, client, &hdmiphy_ops);
150 293
151 v4l2_i2c_subdev_init(&sd, client, &hdmiphy_ops);
152 dev_info(&client->dev, "probe successful\n"); 294 dev_info(&client->dev, "probe successful\n");
153 return 0; 295 return 0;
154} 296}
155 297
156static int __devexit hdmiphy_remove(struct i2c_client *client) 298static int __devexit hdmiphy_remove(struct i2c_client *client)
157{ 299{
300 struct v4l2_subdev *sd = i2c_get_clientdata(client);
301 struct hdmiphy_ctx *ctx = sd_to_ctx(sd);
302
303 kfree(ctx);
158 dev_info(&client->dev, "remove successful\n"); 304 dev_info(&client->dev, "remove successful\n");
305
159 return 0; 306 return 0;
160} 307}
161 308
162static const struct i2c_device_id hdmiphy_id[] = { 309static const struct i2c_device_id hdmiphy_id[] = {
163 { "hdmiphy", 0 }, 310 { "hdmiphy", (unsigned long)hdmiphy_conf_exynos4210 },
311 { "hdmiphy-s5pv210", (unsigned long)hdmiphy_conf_s5pv210 },
312 { "hdmiphy-exynos4210", (unsigned long)hdmiphy_conf_exynos4210 },
313 { "hdmiphy-exynos4212", (unsigned long)hdmiphy_conf_exynos4212 },
314 { "hdmiphy-exynos4412", (unsigned long)hdmiphy_conf_exynos4412 },
164 { }, 315 { },
165}; 316};
166MODULE_DEVICE_TABLE(i2c, hdmiphy_id); 317MODULE_DEVICE_TABLE(i2c, hdmiphy_id);