blob: 05de74e17d3f15371db7451794cd77576d4f272d [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/i2c.h>
14#include <linux/types.h>
15#include <linux/bitops.h>
16#include <linux/adv7520.h>
17#include <linux/time.h>
18#include <linux/completion.h>
19#include <linux/wakelock.h>
Ravishangar Kalyanam120232e2011-08-05 19:13:55 -070020#include <linux/clk.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070021#include <asm/atomic.h>
22#include "msm_fb.h"
23
24#define DEBUG
25#define DEV_DBG_PREFIX "HDMI: "
26
27#include "external_common.h"
28
29/* #define PORT_DEBUG */
30/* #define TESTING_FORCE_480p */
31
32#define HPD_DUTY_CYCLE 4 /*secs*/
33
34static struct external_common_state_type hdmi_common;
35
36static struct i2c_client *hclient;
Ravishangar Kalyanam120232e2011-08-05 19:13:55 -070037static struct clk *tv_enc_clk;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070038
39static bool chip_power_on = FALSE; /* For chip power on/off */
40static bool enable_5v_on = FALSE;
41static bool hpd_power_on = FALSE;
42static atomic_t comm_power_on; /* For dtv power on/off (I2C) */
43static int suspend_count;
44
45static u8 reg[256]; /* HDMI panel registers */
46
47struct hdmi_data {
48 struct msm_hdmi_platform_data *pd;
49 struct work_struct isr_work;
50};
51static struct hdmi_data *dd;
52static struct work_struct hpd_timer_work;
53
54#ifdef CONFIG_FB_MSM_HDMI_ADV7520_PANEL_HDCP_SUPPORT
55static struct work_struct hdcp_handle_work;
56static int hdcp_activating;
57static DEFINE_MUTEX(hdcp_state_mutex);
58static int has_hdcp_hw_support = true;
59#endif
60
61static struct timer_list hpd_timer;
62static struct timer_list hpd_duty_timer;
63static struct work_struct hpd_duty_work;
64static unsigned int monitor_sense;
65static boolean hpd_cable_chg_detected;
66
67struct wake_lock wlock;
68
69/* Change HDMI state */
70static void change_hdmi_state(int online)
71{
72 if (!external_common_state)
73 return;
74
75 mutex_lock(&external_common_state_hpd_mutex);
76 external_common_state->hpd_state = online;
77 mutex_unlock(&external_common_state_hpd_mutex);
78
79 if (!external_common_state->uevent_kobj)
80 return;
81
82 if (online)
83 kobject_uevent(external_common_state->uevent_kobj,
84 KOBJ_ONLINE);
85 else
86 kobject_uevent(external_common_state->uevent_kobj,
87 KOBJ_OFFLINE);
88 DEV_INFO("adv7520_uevent: %d [suspend# %d]\n", online, suspend_count);
89}
90
91
92/*
93 * Read a value from a register on ADV7520 device
94 * If sucessfull returns value read , otherwise error.
95 */
96static u8 adv7520_read_reg(struct i2c_client *client, u8 reg)
97{
98 int err;
99 struct i2c_msg msg[2];
100 u8 reg_buf[] = { reg };
101 u8 data_buf[] = { 0 };
102
103 if (!client->adapter)
104 return -ENODEV;
105 if (!atomic_read(&comm_power_on)) {
106 DEV_WARN("%s: WARN: missing GPIO power\n", __func__);
107 return -ENODEV;
108 }
109
110 msg[0].addr = client->addr;
111 msg[0].flags = 0;
112 msg[0].len = 1;
113 msg[0].buf = reg_buf;
114
115 msg[1].addr = client->addr;
116 msg[1].flags = I2C_M_RD;
117 msg[1].len = 1;
118 msg[1].buf = data_buf;
119
120 err = i2c_transfer(client->adapter, msg, 2);
121
122 if (err < 0) {
123 DEV_INFO("%s: I2C err: %d\n", __func__, err);
124 return err;
125 }
126
127#ifdef PORT_DEBUG
128 DEV_INFO("HDMI[%02x] [R] %02x\n", reg, data);
129#endif
130 return *data_buf;
131}
132
133/*
134 * Write a value to a register on adv7520 device.
135 * Returns zero if successful, or non-zero otherwise.
136 */
137static int adv7520_write_reg(struct i2c_client *client, u8 reg, u8 val)
138{
139 int err;
140 struct i2c_msg msg[1];
141 unsigned char data[2];
142
143 if (!client->adapter)
144 return -ENODEV;
145 if (!atomic_read(&comm_power_on)) {
146 DEV_WARN("%s: WARN: missing GPIO power\n", __func__);
147 return -ENODEV;
148 }
149
150 msg->addr = client->addr;
151 msg->flags = 0;
152 msg->len = 2;
153 msg->buf = data;
154 data[0] = reg;
155 data[1] = val;
156
157 err = i2c_transfer(client->adapter, msg, 1);
158 if (err >= 0)
159 return 0;
160#ifdef PORT_DEBUG
161 DEV_INFO("HDMI[%02x] [W] %02x [%d]\n", reg, val, err);
162#endif
163 return err;
164}
165
166#ifdef CONFIG_FB_MSM_HDMI_ADV7520_PANEL_HDCP_SUPPORT
167static void adv7520_close_hdcp_link(void)
168{
169 if (!external_common_state->hdcp_active && !hdcp_activating)
170 return;
171
172 DEV_INFO("HDCP: Close link\n");
173
174 reg[0xD5] = adv7520_read_reg(hclient, 0xD5);
175 reg[0xD5] &= 0xFE;
176 adv7520_write_reg(hclient, 0xD5, (u8)reg[0xD5]);
177
178 reg[0x16] = adv7520_read_reg(hclient, 0x16);
179 reg[0x16] &= 0xFE;
180 adv7520_write_reg(hclient, 0x16, (u8)reg[0x16]);
181
182 /* UnMute Audio */
183 adv7520_write_reg(hclient, 0x0C, (u8)0x84);
184
185 external_common_state->hdcp_active = FALSE;
186 mutex_lock(&hdcp_state_mutex);
187 hdcp_activating = FALSE;
188 mutex_unlock(&hdcp_state_mutex);
189}
190
191static void adv7520_comm_power(int on, int show);
192static void adv7520_hdcp_enable(struct work_struct *work)
193{
194 DEV_INFO("HDCP: Start reg[0xaf]=%02x (mute audio)\n", reg[0xaf]);
195
196 adv7520_comm_power(1, 1);
197
198 /* Mute Audio */
199 adv7520_write_reg(hclient, 0x0C, (u8)0xC3);
200
201 msleep(200);
202 /* Wait for BKSV ready interrupt */
203 /* Read BKSV's keys from HDTV */
204 reg[0xBF] = adv7520_read_reg(hclient, 0xBF);
205 reg[0xC0] = adv7520_read_reg(hclient, 0xC0);
206 reg[0xC1] = adv7520_read_reg(hclient, 0xC1);
207 reg[0xC2] = adv7520_read_reg(hclient, 0xC2);
208 reg[0xc3] = adv7520_read_reg(hclient, 0xC3);
209
210 DEV_DBG("HDCP: BKSV={%02x,%02x,%02x,%02x,%02x}\n", reg[0xbf], reg[0xc0],
211 reg[0xc1], reg[0xc2], reg[0xc3]);
212
213 /* Is SINK repeater */
214 reg[0xBE] = adv7520_read_reg(hclient, 0xBE);
215 if (~(reg[0xBE] & 0x40)) {
216 ; /* compare with revocation list */
217 /* Check 20 1's and 20 zero's */
218 } else {
219 /* Don't implement HDCP if sink as a repeater */
220 adv7520_write_reg(hclient, 0x0C, (u8)0x84);
221 mutex_lock(&hdcp_state_mutex);
222 hdcp_activating = FALSE;
223 mutex_unlock(&hdcp_state_mutex);
224 DEV_WARN("HDCP: Sink Repeater (%02x), (unmute audio)\n",
225 reg[0xbe]);
226
227 adv7520_comm_power(0, 1);
228 return;
229 }
230
231 msleep(200);
232 reg[0xB8] = adv7520_read_reg(hclient, 0xB8);
233 DEV_INFO("HDCP: Status reg[0xB8] is %02x\n", reg[0xb8]);
234 if (reg[0xb8] & 0x40) {
235 /* UnMute Audio */
236 adv7520_write_reg(hclient, 0x0C, (u8)0x84);
237 DEV_INFO("HDCP: A/V content Encrypted (unmute audio)\n");
238 external_common_state->hdcp_active = TRUE;
239 }
240 adv7520_comm_power(0, 1);
241
242 mutex_lock(&hdcp_state_mutex);
243 hdcp_activating = FALSE;
244 mutex_unlock(&hdcp_state_mutex);
245}
246#endif
247
248static int adv7520_read_edid_block(int block, uint8 *edid_buf)
249{
250 u8 r = 0;
251 int ret;
252 struct i2c_msg msg[] = {
253 { .addr = reg[0x43] >> 1,
254 .flags = 0,
255 .len = 1,
256 .buf = &r },
257 { .addr = reg[0x43] >> 1,
258 .flags = I2C_M_RD,
259 .len = 0x100,
260 .buf = edid_buf } };
261
262 if (block > 0)
263 return 0;
264 ret = i2c_transfer(hclient->adapter, msg, 2);
265 DEV_DBG("EDID block: addr=%02x, ret=%d\n", reg[0x43] >> 1, ret);
266 return (ret < 2) ? -ENODEV : 0;
267}
268
269static void adv7520_read_edid(void)
270{
271 external_common_state->read_edid_block = adv7520_read_edid_block;
272 if (hdmi_common_read_edid()) {
273 u8 timeout;
274 DEV_INFO("%s: retry\n", __func__);
275 adv7520_write_reg(hclient, 0xc9, 0x13);
276 msleep(500);
277 timeout = (adv7520_read_reg(hclient, 0x96) & (1 << 2));
278 if (timeout) {
279 hdmi_common_read_edid();
280 }
281 }
282}
283
284static void adv7520_chip_on(void)
285{
286 if (!chip_power_on) {
287 /* Get the current register holding the power bit. */
288 unsigned long reg0xaf = adv7520_read_reg(hclient, 0xaf);
289
290 dd->pd->core_power(1, 1);
291
292 /* Set the HDMI select bit. */
293 set_bit(1, &reg0xaf);
294 DEV_INFO("%s: turn on chip power\n", __func__);
295 adv7520_write_reg(hclient, 0x41, 0x10);
296 adv7520_write_reg(hclient, 0xaf, (u8)reg0xaf);
297 chip_power_on = TRUE;
298 } else
299 DEV_INFO("%s: chip already has power\n", __func__);
300}
301
302static void adv7520_chip_off(void)
303{
304 if (chip_power_on) {
305#ifdef CONFIG_FB_MSM_HDMI_ADV7520_PANEL_HDCP_SUPPORT
306 if (has_hdcp_hw_support)
307 adv7520_close_hdcp_link();
308#endif
309
310 DEV_INFO("%s: turn off chip power\n", __func__);
311 adv7520_write_reg(hclient, 0x41, 0x50);
312 dd->pd->core_power(0, 1);
313 chip_power_on = FALSE;
314 } else
315 DEV_INFO("%s: chip is already off\n", __func__);
316
317 monitor_sense = 0;
318 hpd_cable_chg_detected = FALSE;
319
320 if (enable_5v_on) {
321 dd->pd->enable_5v(0);
322 enable_5v_on = FALSE;
323 }
324}
325
326/* Power ON/OFF ADV7520 chip */
327static void adv7520_isr_w(struct work_struct *work);
328static void adv7520_comm_power(int on, int show)
329{
330 if (!on)
331 atomic_dec(&comm_power_on);
332 dd->pd->comm_power(on, 0/*show*/);
333 if (on)
334 atomic_inc(&comm_power_on);
335}
336
337#ifdef CONFIG_FB_MSM_HDMI_ADV7520_PANEL_HDCP_SUPPORT
338static void adv7520_start_hdcp(void);
339#endif
340static int adv7520_power_on(struct platform_device *pdev)
341{
342 struct msm_fb_data_type *mfd = platform_get_drvdata(pdev);
343
Ravishangar Kalyanam120232e2011-08-05 19:13:55 -0700344 clk_enable(tv_enc_clk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700345 external_common_state->dev = &pdev->dev;
346 if (mfd != NULL) {
347 DEV_INFO("adv7520_power: ON (%dx%d %d)\n",
348 mfd->var_xres, mfd->var_yres, mfd->var_pixclock);
349 hdmi_common_get_video_format_from_drv_data(mfd);
350 }
351
352 adv7520_comm_power(1, 1);
353 /* Check if HPD is signaled */
354 if (adv7520_read_reg(hclient, 0x42) & (1 << 6)) {
355 DEV_INFO("power_on: cable detected\n");
356 monitor_sense = adv7520_read_reg(hclient, 0xC6);
357#ifdef CONFIG_FB_MSM_HDMI_ADV7520_PANEL_HDCP_SUPPORT
358 if (has_hdcp_hw_support) {
359 if (!hdcp_activating)
360 adv7520_start_hdcp();
361 }
362#endif
363 } else
364 DEV_INFO("power_on: cable NOT detected\n");
365 adv7520_comm_power(0, 1);
366 wake_lock(&wlock);
367
368 return 0;
369}
370
371static int adv7520_power_off(struct platform_device *pdev)
372{
373 DEV_INFO("power_off\n");
374 adv7520_comm_power(1, 1);
375 adv7520_chip_off();
376 wake_unlock(&wlock);
377 adv7520_comm_power(0, 1);
Ravishangar Kalyanam120232e2011-08-05 19:13:55 -0700378 clk_disable(tv_enc_clk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700379 return 0;
380}
381
382
383/* AV7520 chip specific initialization */
384static void adv7520_chip_init(void)
385{
386 /* Initialize the variables used to read/write the ADV7520 chip. */
387 memset(&reg, 0xff, sizeof(reg));
388
389 /* Get the values from the "Fixed Registers That Must Be Set". */
390 reg[0x98] = adv7520_read_reg(hclient, 0x98);
391 reg[0x9c] = adv7520_read_reg(hclient, 0x9c);
392 reg[0x9d] = adv7520_read_reg(hclient, 0x9d);
393 reg[0xa2] = adv7520_read_reg(hclient, 0xa2);
394 reg[0xa3] = adv7520_read_reg(hclient, 0xa3);
395 reg[0xde] = adv7520_read_reg(hclient, 0xde);
396
397 /* Get the "HDMI/DVI Selection" register. */
398 reg[0xaf] = adv7520_read_reg(hclient, 0xaf);
399
400 /* Read Packet Memory I2C Address */
401 reg[0x45] = adv7520_read_reg(hclient, 0x45);
402
403 /* Hard coded values provided by ADV7520 data sheet. */
404 reg[0x98] = 0x03;
405 reg[0x9c] = 0x38;
406 reg[0x9d] = 0x61;
407 reg[0xa2] = 0x94;
408 reg[0xa3] = 0x94;
409 reg[0xde] = 0x88;
410
411 /* Set the HDMI select bit. */
412 reg[0xaf] |= 0x16;
413
414 /* Set the audio related registers. */
415 reg[0x01] = 0x00;
416 reg[0x02] = 0x2d;
417 reg[0x03] = 0x80;
418 reg[0x0a] = 0x4d;
419 reg[0x0b] = 0x0e;
420 reg[0x0c] = 0x84;
421 reg[0x0d] = 0x10;
422 reg[0x12] = 0x00;
423 reg[0x14] = 0x00;
424 reg[0x15] = 0x20;
425 reg[0x44] = 0x79;
426 reg[0x73] = 0x01;
427 reg[0x76] = 0x00;
428
429 /* Set 720p display related registers */
430 reg[0x16] = 0x00;
431
432 reg[0x18] = 0x46;
433 reg[0x55] = 0x00;
434 reg[0x3c] = 0x04;
435
436 /* Set Interrupt Mask register for HPD/HDCP */
437 reg[0x94] = 0xC0;
438#ifdef CONFIG_FB_MSM_HDMI_ADV7520_PANEL_HDCP_SUPPORT
439 if (has_hdcp_hw_support)
440 reg[0x95] = 0xC0;
441 else
442 reg[0x95] = 0x00;
443#else
444 reg[0x95] = 0x00;
445#endif
446 adv7520_write_reg(hclient, 0x94, reg[0x94]);
447 adv7520_write_reg(hclient, 0x95, reg[0x95]);
448
449 /* Set Packet Memory I2C Address */
450 reg[0x45] = 0x74;
451
452 /* Set the values from the "Fixed Registers That Must Be Set". */
453 adv7520_write_reg(hclient, 0x98, reg[0x98]);
454 adv7520_write_reg(hclient, 0x9c, reg[0x9c]);
455 adv7520_write_reg(hclient, 0x9d, reg[0x9d]);
456 adv7520_write_reg(hclient, 0xa2, reg[0xa2]);
457 adv7520_write_reg(hclient, 0xa3, reg[0xa3]);
458 adv7520_write_reg(hclient, 0xde, reg[0xde]);
459
460 /* Set the "HDMI/DVI Selection" register. */
461 adv7520_write_reg(hclient, 0xaf, reg[0xaf]);
462
463 /* Set EDID Monitor address */
464 reg[0x43] = 0x7E;
465 adv7520_write_reg(hclient, 0x43, reg[0x43]);
466
467 /* Enable the i2s audio input. */
468 adv7520_write_reg(hclient, 0x01, reg[0x01]);
469 adv7520_write_reg(hclient, 0x02, reg[0x02]);
470 adv7520_write_reg(hclient, 0x03, reg[0x03]);
471 adv7520_write_reg(hclient, 0x0a, reg[0x0a]);
472 adv7520_write_reg(hclient, 0x0b, reg[0x0b]);
473 adv7520_write_reg(hclient, 0x0c, reg[0x0c]);
474 adv7520_write_reg(hclient, 0x0d, reg[0x0d]);
475 adv7520_write_reg(hclient, 0x12, reg[0x12]);
476 adv7520_write_reg(hclient, 0x14, reg[0x14]);
477 adv7520_write_reg(hclient, 0x15, reg[0x15]);
478 adv7520_write_reg(hclient, 0x44, reg[0x44]);
479 adv7520_write_reg(hclient, 0x73, reg[0x73]);
480 adv7520_write_reg(hclient, 0x76, reg[0x76]);
481
482 /* Enable 720p display */
483 adv7520_write_reg(hclient, 0x16, reg[0x16]);
484 adv7520_write_reg(hclient, 0x18, reg[0x18]);
485 adv7520_write_reg(hclient, 0x55, reg[0x55]);
486 adv7520_write_reg(hclient, 0x3c, reg[0x3c]);
487
488 /* Set Packet Memory address to avoid conflict
489 with Bosch Accelerometer */
490 adv7520_write_reg(hclient, 0x45, reg[0x45]);
491
492 /* Ensure chip is in low-power state */
493 adv7520_write_reg(hclient, 0x41, 0x50);
494}
495
496#ifdef CONFIG_FB_MSM_HDMI_ADV7520_PANEL_HDCP_SUPPORT
497static void adv7520_start_hdcp(void)
498{
499 mutex_lock(&hdcp_state_mutex);
500 if (hdcp_activating) {
501 DEV_WARN("adv7520_timer: HDCP already"
502 " activating, skipping\n");
503 mutex_unlock(&hdcp_state_mutex);
504 return;
505 }
506 hdcp_activating = TRUE;
507 mutex_unlock(&hdcp_state_mutex);
508
509 del_timer(&hpd_duty_timer);
510
511 adv7520_comm_power(1, 1);
512
513 if (!enable_5v_on) {
514 dd->pd->enable_5v(1);
515 enable_5v_on = TRUE;
516 adv7520_chip_on();
517 }
518
519 /* request for HDCP */
520 reg[0xaf] = adv7520_read_reg(hclient, 0xaf);
521 reg[0xaf] |= 0x90;
522 adv7520_write_reg(hclient, 0xaf, reg[0xaf]);
523 reg[0xaf] = adv7520_read_reg(hclient, 0xaf);
524
525 reg[0xba] = adv7520_read_reg(hclient, 0xba);
526 reg[0xba] |= 0x10;
527 adv7520_write_reg(hclient, 0xba, reg[0xba]);
528 reg[0xba] = adv7520_read_reg(hclient, 0xba);
529 adv7520_comm_power(0, 1);
530
531 DEV_INFO("HDCP: reg[0xaf]=0x%02x, reg[0xba]=0x%02x, waiting for BKSV\n",
532 reg[0xaf], reg[0xba]);
533
534 /* will check for HDCP Error or BKSV ready */
535 mod_timer(&hpd_duty_timer, jiffies + HZ/2);
536}
537#endif
538
539static void adv7520_hpd_timer_w(struct work_struct *work)
540{
541 if (!external_common_state->hpd_feature_on) {
542 DEV_INFO("adv7520_timer: skipping, feature off\n");
543 return;
544 }
545
546 if ((monitor_sense & 0x4) && !external_common_state->hpd_state) {
547 int timeout;
548 DEV_DBG("adv7520_timer: Cable Detected\n");
549 adv7520_comm_power(1, 1);
550 adv7520_chip_on();
551
552 if (hpd_cable_chg_detected) {
553 hpd_cable_chg_detected = FALSE;
554 /* Ensure 5V to read EDID */
555 if (!enable_5v_on) {
556 dd->pd->enable_5v(1);
557 enable_5v_on = TRUE;
558 }
559 msleep(500);
560 timeout = (adv7520_read_reg(hclient, 0x96) & (1 << 2));
561 if (timeout) {
562 DEV_DBG("adv7520_timer: EDID-Ready..\n");
563 adv7520_read_edid();
564 } else
565 DEV_DBG("adv7520_timer: EDID TIMEOUT (C9=%02x)"
566 "\n", adv7520_read_reg(hclient, 0xC9));
567 }
568#ifdef TESTING_FORCE_480p
569 external_common_state->disp_mode_list.num_of_elements = 1;
570 external_common_state->disp_mode_list.disp_mode_list[0] =
571 HDMI_VFRMT_720x480p60_16_9;
572#endif
573 adv7520_comm_power(0, 1);
574#ifndef CONFIG_FB_MSM_HDMI_ADV7520_PANEL_HDCP_SUPPORT
575 /* HDMI_5V_EN not needed anymore */
576 if (enable_5v_on) {
577 DEV_DBG("adv7520_timer: EDID done, no HDCP, 5V not "
578 "needed anymore\n");
579 dd->pd->enable_5v(0);
580 enable_5v_on = FALSE;
581 }
582#endif
583 change_hdmi_state(1);
584 } else if (external_common_state->hpd_state) {
585 adv7520_comm_power(1, 1);
586 adv7520_chip_off();
587 adv7520_comm_power(0, 1);
588 DEV_DBG("adv7520_timer: Cable Removed\n");
589 change_hdmi_state(0);
590 }
591}
592
593static void adv7520_hpd_timer_f(unsigned long data)
594{
595 schedule_work(&hpd_timer_work);
596}
597
598static void adv7520_isr_w(struct work_struct *work)
599{
600 static int state_count;
601 static u8 last_reg0x96;
602 u8 reg0xc8;
603 u8 reg0x96;
604#ifdef CONFIG_FB_MSM_HDMI_ADV7520_PANEL_HDCP_SUPPORT
605 static u8 last_reg0x97;
606 u8 reg0x97 = 0;
607#endif
608 if (!external_common_state->hpd_feature_on) {
609 DEV_DBG("adv7520_irq: skipping, hpd off\n");
610 return;
611 }
612
613 adv7520_comm_power(1, 1);
614 reg0x96 = adv7520_read_reg(hclient, 0x96);
615#ifdef CONFIG_FB_MSM_HDMI_ADV7520_PANEL_HDCP_SUPPORT
616 if (has_hdcp_hw_support) {
617 reg0x97 = adv7520_read_reg(hclient, 0x97);
618 /* Clearing the Interrupts */
619 adv7520_write_reg(hclient, 0x97, reg0x97);
620 }
621#endif
622 /* Clearing the Interrupts */
623 adv7520_write_reg(hclient, 0x96, reg0x96);
624
625 if ((reg0x96 == 0xC0) || (reg0x96 & 0x40)) {
626#ifdef DEBUG
627 unsigned int hpd_state = adv7520_read_reg(hclient, 0x42);
628#endif
629 monitor_sense = adv7520_read_reg(hclient, 0xC6);
630 DEV_DBG("adv7520_irq: reg[0x42]=%02x && reg[0xC6]=%02x\n",
631 hpd_state, monitor_sense);
632
633 if (!enable_5v_on) {
634 dd->pd->enable_5v(1);
635 enable_5v_on = TRUE;
636 }
637 if (!hpd_power_on) {
638 dd->pd->core_power(1, 1);
639 hpd_power_on = TRUE;
640 }
641
642 /* Timer for catching interrupt debouning */
643 DEV_DBG("adv7520_irq: Timer in .5sec\n");
644 hpd_cable_chg_detected = TRUE;
645 mod_timer(&hpd_timer, jiffies + HZ/2);
646 }
647#ifdef CONFIG_FB_MSM_HDMI_ADV7520_PANEL_HDCP_SUPPORT
648 if (has_hdcp_hw_support) {
649 if (hdcp_activating) {
650 /* HDCP controller error Interrupt */
651 if (reg0x97 & 0x80) {
652 DEV_ERR("adv7520_irq: HDCP_ERROR\n");
653 state_count = 0;
654 adv7520_close_hdcp_link();
655 /* BKSV Ready interrupts */
656 } else if (reg0x97 & 0x40) {
657 DEV_INFO("adv7520_irq: BKSV keys ready, Begin"
658 " HDCP encryption\n");
659 state_count = 0;
660 schedule_work(&hdcp_handle_work);
661 } else if (++state_count > 2 && (monitor_sense & 0x4)) {
662 DEV_INFO("adv7520_irq: Still waiting for BKSV,"
663 "restart HDCP\n");
664 hdcp_activating = FALSE;
665 state_count = 0;
666 adv7520_chip_off();
667 adv7520_start_hdcp();
668 }
669 reg0xc8 = adv7520_read_reg(hclient, 0xc8);
670 DEV_INFO("adv7520_irq: DDC controller reg[0xC8]=0x%02x,"
671 "state_count=%d, monitor_sense=%x\n",
672 reg0xc8, state_count, monitor_sense);
673 } else if (!external_common_state->hdcp_active
674 && (monitor_sense & 0x4)) {
675 DEV_INFO("adv7520_irq: start HDCP with"
676 " monitor sense\n");
677 state_count = 0;
678 adv7520_start_hdcp();
679 } else
680 state_count = 0;
681 if (last_reg0x97 != reg0x97 || last_reg0x96 != reg0x96)
682 DEV_DBG("adv7520_irq: reg[0x96]=%02x "
683 "reg[0x97]=%02x: HDCP: %d\n", reg0x96, reg0x97,
684 external_common_state->hdcp_active);
685 last_reg0x97 = reg0x97;
686 } else {
687 if (last_reg0x96 != reg0x96)
688 DEV_DBG("adv7520_irq: reg[0x96]=%02x\n", reg0x96);
689 }
690#else
691 if (last_reg0x96 != reg0x96)
692 DEV_DBG("adv7520_irq: reg[0x96]=%02x\n", reg0x96);
693#endif
694 last_reg0x96 = reg0x96;
695 adv7520_comm_power(0, 1);
696}
697
698static void adv7520_hpd_duty_work(struct work_struct *work)
699{
700 if (!external_common_state->hpd_feature_on) {
701 DEV_WARN("%s: hpd feature is off, skipping\n", __func__);
702 return;
703 }
704
705 dd->pd->core_power(1, 0);
706 msleep(10);
707 adv7520_isr_w(NULL);
708 dd->pd->core_power(0, 0);
709}
710
711static void adv7520_hpd_duty_timer_f(unsigned long data)
712{
713 if (!external_common_state->hpd_feature_on) {
714 DEV_WARN("%s: hpd feature is off, skipping\n", __func__);
715 return;
716 }
717
718 mod_timer(&hpd_duty_timer, jiffies + HPD_DUTY_CYCLE*HZ);
719 schedule_work(&hpd_duty_work);
720}
721
722static const struct i2c_device_id adv7520_id[] = {
723 { ADV7520_DRV_NAME , 0},
724 {}
725};
726
727static struct msm_fb_panel_data hdmi_panel_data = {
728 .on = adv7520_power_on,
729 .off = adv7520_power_off,
730};
731
732static struct platform_device hdmi_device = {
733 .name = ADV7520_DRV_NAME ,
734 .id = 2,
735 .dev = {
736 .platform_data = &hdmi_panel_data,
737 }
738};
739
740static void adv7520_ensure_init(void)
741{
742 static boolean init_done;
743 if (!init_done) {
744 int rc = dd->pd->init_irq();
745 if (rc) {
746 DEV_ERR("adv7520_init: init_irq: %d\n", rc);
747 return;
748 }
749
750 init_done = TRUE;
751 }
752 DEV_INFO("adv7520_init: chip init\n");
753 adv7520_comm_power(1, 1);
754 adv7520_chip_init();
755 adv7520_comm_power(0, 1);
756}
757
758static int adv7520_hpd_feature(int on)
759{
760 int rc = 0;
761
762 if (!on) {
763 if (enable_5v_on) {
764 dd->pd->enable_5v(0);
765 enable_5v_on = FALSE;
766 }
767 if (hpd_power_on) {
768 dd->pd->core_power(0, 1);
769 hpd_power_on = FALSE;
770 }
771
772 DEV_DBG("adv7520_hpd: %d: stop duty timer\n", on);
773 del_timer(&hpd_timer);
774 del_timer(&hpd_duty_timer);
775 external_common_state->hpd_state = 0;
776 }
777
778 if (on) {
779 dd->pd->core_power(1, 0);
780 adv7520_ensure_init();
781
782 adv7520_comm_power(1, 1);
783 monitor_sense = adv7520_read_reg(hclient, 0xC6);
784 DEV_DBG("adv7520_irq: reg[0xC6]=%02x\n", monitor_sense);
785 adv7520_comm_power(0, 1);
786 dd->pd->core_power(0, 0);
787
788 if (monitor_sense & 0x4) {
789 if (!enable_5v_on) {
790 dd->pd->enable_5v(1);
791 enable_5v_on = TRUE;
792 }
793 if (!hpd_power_on) {
794 dd->pd->core_power(1, 1);
795 hpd_power_on = TRUE;
796 }
797
798 hpd_cable_chg_detected = TRUE;
799 mod_timer(&hpd_timer, jiffies + HZ/2);
800 }
801
802 DEV_DBG("adv7520_hpd: %d start duty timer\n", on);
803 mod_timer(&hpd_duty_timer, jiffies + HZ/100);
804 }
805
806 DEV_INFO("adv7520_hpd: %d\n", on);
807 return rc;
808}
809
810static int __devinit
811 adv7520_probe(struct i2c_client *client, const struct i2c_device_id *id)
812{
813 int rc;
814 struct platform_device *fb_dev;
815
816 dd = kzalloc(sizeof *dd, GFP_KERNEL);
817 if (!dd) {
818 rc = -ENOMEM;
819 goto probe_exit;
820 }
821
822 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
823 return -ENODEV;
824
825 external_common_state->dev = &client->dev;
826
827 /* Init real i2c_client */
828 hclient = client;
829
830 i2c_set_clientdata(client, dd);
831 dd->pd = client->dev.platform_data;
832 if (!dd->pd) {
833 rc = -ENODEV;
834 goto probe_free;
835 }
836
837 INIT_WORK(&dd->isr_work, adv7520_isr_w);
838 INIT_WORK(&hpd_timer_work, adv7520_hpd_timer_w);
839#ifdef CONFIG_FB_MSM_HDMI_ADV7520_PANEL_HDCP_SUPPORT
840 if (dd->pd->check_hdcp_hw_support)
841 has_hdcp_hw_support = dd->pd->check_hdcp_hw_support();
842
843 if (has_hdcp_hw_support)
844 INIT_WORK(&hdcp_handle_work, adv7520_hdcp_enable);
845 else
846 DEV_INFO("%s: no hdcp hw support.\n", __func__);
847#endif
848
849 init_timer(&hpd_timer);
850 hpd_timer.function = adv7520_hpd_timer_f;
851 hpd_timer.data = (unsigned long)NULL;
852 hpd_timer.expires = 0xffffffff;
853 add_timer(&hpd_timer);
854
855 external_common_state->hpd_feature = adv7520_hpd_feature;
856 DEV_INFO("adv7520_probe: HPD detection on request\n");
857 init_timer(&hpd_duty_timer);
858 hpd_duty_timer.function = adv7520_hpd_duty_timer_f;
859 hpd_duty_timer.data = (unsigned long)NULL;
860 hpd_duty_timer.expires = 0xffffffff;
861 add_timer(&hpd_duty_timer);
862 INIT_WORK(&hpd_duty_work, adv7520_hpd_duty_work);
863 DEV_INFO("adv7520_probe: HPD detection ON (duty)\n");
864
865 fb_dev = msm_fb_add_device(&hdmi_device);
866
867 if (fb_dev) {
868 rc = external_common_state_create(fb_dev);
869 if (rc)
870 goto probe_free;
871 } else
872 DEV_ERR("adv7520_probe: failed to add fb device\n");
873
874 return 0;
875
876probe_free:
877 kfree(dd);
878 dd = NULL;
879probe_exit:
880 return rc;
881
882}
883
884static int __devexit adv7520_remove(struct i2c_client *client)
885{
886 if (!client->adapter) {
887 DEV_ERR("%s: No HDMI Device\n", __func__);
888 return -ENODEV;
889 }
890 wake_lock_destroy(&wlock);
891 kfree(dd);
892 dd = NULL;
893 return 0;
894}
895
896#ifdef CONFIG_SUSPEND
897static int adv7520_i2c_suspend(struct device *dev)
898{
899 DEV_INFO("%s\n", __func__);
900
901 ++suspend_count;
902
903 if (external_common_state->hpd_feature_on) {
904 DEV_DBG("%s: stop duty timer\n", __func__);
905 del_timer(&hpd_duty_timer);
906 del_timer(&hpd_timer);
907 }
908
909 /* Turn off LDO8 and go into low-power state */
910 if (chip_power_on) {
911 DEV_DBG("%s: turn off power\n", __func__);
912 adv7520_comm_power(1, 1);
913 adv7520_write_reg(hclient, 0x41, 0x50);
914 adv7520_comm_power(0, 1);
915 dd->pd->core_power(0, 1);
916 }
917
918 return 0;
919}
920
921static int adv7520_i2c_resume(struct device *dev)
922{
923 DEV_INFO("%s\n", __func__);
924
925 /* Turn on LDO8 and go into normal-power state */
926 if (chip_power_on) {
927 DEV_DBG("%s: turn on power\n", __func__);
928 dd->pd->core_power(1, 1);
929 adv7520_comm_power(1, 1);
930 adv7520_write_reg(hclient, 0x41, 0x10);
931 adv7520_comm_power(0, 1);
932 }
933
934 if (external_common_state->hpd_feature_on) {
935 DEV_DBG("%s: start duty timer\n", __func__);
936 mod_timer(&hpd_duty_timer, jiffies + HPD_DUTY_CYCLE*HZ);
937 }
938
939 return 0;
940}
941#else
942#define adv7520_i2c_suspend NULL
943#define adv7520_i2c_resume NULL
944#endif
945
946static const struct dev_pm_ops adv7520_device_pm_ops = {
947 .suspend = adv7520_i2c_suspend,
948 .resume = adv7520_i2c_resume,
949};
950
951static struct i2c_driver hdmi_i2c_driver = {
952 .driver = {
953 .name = ADV7520_DRV_NAME,
954 .owner = THIS_MODULE,
955 .pm = &adv7520_device_pm_ops,
956 },
957 .probe = adv7520_probe,
958 .id_table = adv7520_id,
959 .remove = __devexit_p(adv7520_remove),
960};
961
962static int __init adv7520_init(void)
963{
964 int rc;
965
966 pr_info("%s\n", __func__);
967 external_common_state = &hdmi_common;
968 external_common_state->video_resolution = HDMI_VFRMT_1280x720p60_16_9;
Ravishangar Kalyanam120232e2011-08-05 19:13:55 -0700969
970 tv_enc_clk = clk_get(NULL, "tv_enc_clk");
971 if (IS_ERR(tv_enc_clk)) {
972 printk(KERN_ERR "error: can't get tv_enc_clk!\n");
973 return IS_ERR(tv_enc_clk);
974 }
975
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700976 HDMI_SETUP_LUT(640x480p60_4_3); /* 25.20MHz */
977 HDMI_SETUP_LUT(720x480p60_16_9); /* 27.03MHz */
978 HDMI_SETUP_LUT(1280x720p60_16_9); /* 74.25MHz */
979
980 HDMI_SETUP_LUT(720x576p50_16_9); /* 27.00MHz */
981 HDMI_SETUP_LUT(1280x720p50_16_9); /* 74.25MHz */
982
983 hdmi_common_init_panel_info(&hdmi_panel_data.panel_info);
984
985 rc = i2c_add_driver(&hdmi_i2c_driver);
986 if (rc) {
987 pr_err("hdmi_init FAILED: i2c_add_driver rc=%d\n", rc);
988 goto init_exit;
989 }
990
991 if (machine_is_msm7x30_surf() || machine_is_msm8x55_surf()) {
992 short *hdtv_mux = (short *)ioremap(0x8e000170 , 0x100);
993 *hdtv_mux++ = 0x020b;
994 *hdtv_mux = 0x8000;
995 iounmap(hdtv_mux);
996 }
997 wake_lock_init(&wlock, WAKE_LOCK_IDLE, "hdmi_active");
998
999 return 0;
1000
1001init_exit:
Ravishangar Kalyanam120232e2011-08-05 19:13:55 -07001002 if (tv_enc_clk)
1003 clk_put(tv_enc_clk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001004 return rc;
1005}
1006
1007static void __exit adv7520_exit(void)
1008{
1009 i2c_del_driver(&hdmi_i2c_driver);
1010}
1011
1012module_init(adv7520_init);
1013module_exit(adv7520_exit);
1014MODULE_LICENSE("GPL v2");
1015MODULE_VERSION("0.1");
1016MODULE_AUTHOR("Qualcomm Innovation Center, Inc.");
1017MODULE_DESCRIPTION("ADV7520 HDMI driver");