]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/gpu/drm/msm/hdmi/hdmi_phy_8960.c
arm: imx6: defconfig: update tx6 defconfigs
[karo-tx-linux.git] / drivers / gpu / drm / msm / hdmi / hdmi_phy_8960.c
1 /*
2  * Copyright (C) 2013 Red Hat
3  * Author: Rob Clark <robdclark@gmail.com>
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 as published by
7  * the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along with
15  * this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 #include "hdmi.h"
19
20 struct hdmi_phy_8960 {
21         struct hdmi_phy base;
22         struct hdmi *hdmi;
23 };
24 #define to_hdmi_phy_8960(x) container_of(x, struct hdmi_phy_8960, base)
25
26 static void hdmi_phy_8960_destroy(struct hdmi_phy *phy)
27 {
28         struct hdmi_phy_8960 *phy_8960 = to_hdmi_phy_8960(phy);
29         kfree(phy_8960);
30 }
31
32 static void hdmi_phy_8960_reset(struct hdmi_phy *phy)
33 {
34         struct hdmi_phy_8960 *phy_8960 = to_hdmi_phy_8960(phy);
35         struct hdmi *hdmi = phy_8960->hdmi;
36         unsigned int val;
37
38         val = hdmi_read(hdmi, REG_HDMI_PHY_CTRL);
39
40         if (val & HDMI_PHY_CTRL_SW_RESET_LOW) {
41                 /* pull low */
42                 hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
43                                 val & ~HDMI_PHY_CTRL_SW_RESET);
44         } else {
45                 /* pull high */
46                 hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
47                                 val | HDMI_PHY_CTRL_SW_RESET);
48         }
49
50         if (val & HDMI_PHY_CTRL_SW_RESET_PLL_LOW) {
51                 /* pull low */
52                 hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
53                                 val & ~HDMI_PHY_CTRL_SW_RESET_PLL);
54         } else {
55                 /* pull high */
56                 hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
57                                 val | HDMI_PHY_CTRL_SW_RESET_PLL);
58         }
59
60         msleep(100);
61
62         if (val & HDMI_PHY_CTRL_SW_RESET_LOW) {
63                 /* pull high */
64                 hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
65                                 val | HDMI_PHY_CTRL_SW_RESET);
66         } else {
67                 /* pull low */
68                 hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
69                                 val & ~HDMI_PHY_CTRL_SW_RESET);
70         }
71
72         if (val & HDMI_PHY_CTRL_SW_RESET_PLL_LOW) {
73                 /* pull high */
74                 hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
75                                 val | HDMI_PHY_CTRL_SW_RESET_PLL);
76         } else {
77                 /* pull low */
78                 hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
79                                 val & ~HDMI_PHY_CTRL_SW_RESET_PLL);
80         }
81 }
82
83 static void hdmi_phy_8960_powerup(struct hdmi_phy *phy,
84                 unsigned long int pixclock)
85 {
86         struct hdmi_phy_8960 *phy_8960 = to_hdmi_phy_8960(phy);
87         struct hdmi *hdmi = phy_8960->hdmi;
88
89         hdmi_write(hdmi, REG_HDMI_8960_PHY_REG0, 0x1b);
90         hdmi_write(hdmi, REG_HDMI_8960_PHY_REG1, 0xf2);
91         hdmi_write(hdmi, REG_HDMI_8960_PHY_REG4, 0x00);
92         hdmi_write(hdmi, REG_HDMI_8960_PHY_REG5, 0x00);
93         hdmi_write(hdmi, REG_HDMI_8960_PHY_REG6, 0x00);
94         hdmi_write(hdmi, REG_HDMI_8960_PHY_REG7, 0x00);
95         hdmi_write(hdmi, REG_HDMI_8960_PHY_REG8, 0x00);
96         hdmi_write(hdmi, REG_HDMI_8960_PHY_REG9, 0x00);
97         hdmi_write(hdmi, REG_HDMI_8960_PHY_REG10, 0x00);
98         hdmi_write(hdmi, REG_HDMI_8960_PHY_REG11, 0x00);
99         hdmi_write(hdmi, REG_HDMI_8960_PHY_REG3, 0x20);
100 }
101
102 static void hdmi_phy_8960_powerdown(struct hdmi_phy *phy)
103 {
104         struct hdmi_phy_8960 *phy_8960 = to_hdmi_phy_8960(phy);
105         struct hdmi *hdmi = phy_8960->hdmi;
106
107         hdmi_write(hdmi, REG_HDMI_8960_PHY_REG2, 0x7f);
108 }
109
110 static const struct hdmi_phy_funcs hdmi_phy_8960_funcs = {
111                 .destroy = hdmi_phy_8960_destroy,
112                 .reset = hdmi_phy_8960_reset,
113                 .powerup = hdmi_phy_8960_powerup,
114                 .powerdown = hdmi_phy_8960_powerdown,
115 };
116
117 struct hdmi_phy *hdmi_phy_8960_init(struct hdmi *hdmi)
118 {
119         struct hdmi_phy_8960 *phy_8960;
120         struct hdmi_phy *phy = NULL;
121         int ret;
122
123         phy_8960 = kzalloc(sizeof(*phy_8960), GFP_KERNEL);
124         if (!phy_8960) {
125                 ret = -ENOMEM;
126                 goto fail;
127         }
128
129         phy = &phy_8960->base;
130
131         phy->funcs = &hdmi_phy_8960_funcs;
132
133         phy_8960->hdmi = hdmi;
134
135         return phy;
136
137 fail:
138         if (phy)
139                 hdmi_phy_8960_destroy(phy);
140         return ERR_PTR(ret);
141 }