1 #include "rockchip_dp.h"
2 #include <linux/delay.h>
4 static int rockchip_dp_removed(struct hdmi *hdmi_drv)
6 struct dp_dev *dp_dev = hdmi_drv->property->priv;
9 ret = cdn_dp_encoder_disable(dp_dev->dp);
11 dev_warn(hdmi_drv->dev, "dp has been removed twice:%d\n", ret);
12 return HDMI_ERROR_SUCCESS;
15 static int rockchip_dp_enable(struct hdmi *hdmi_drv)
20 static int rockchip_dp_disable(struct hdmi *hdmi_drv)
25 static int rockchip_dp_control_output(struct hdmi *hdmi_drv, int enable)
27 struct dp_dev *dp_dev = hdmi_drv->property->priv;
30 if (enable == HDMI_AV_UNMUTE) {
31 if (!dp_dev->early_suspended) {
32 ret = cdn_dp_encoder_enable(dp_dev->dp);
34 dev_err(hdmi_drv->dev,
35 "dp enable video and audio output error:%d\n", ret);
36 return HDMI_ERROR_FALSE;
39 dev_warn(hdmi_drv->dev,
40 "don't output video and audio after dp has been suspended!\n");
41 } else if (enable & HDMI_VIDEO_MUTE)
42 dev_dbg(hdmi_drv->dev, "dp disable video and audio output !\n");
47 static int rockchip_dp_config_audio(struct hdmi *hdmi_drv,
48 struct hdmi_audio *audio)
53 static int rockchip_dp_config_video(struct hdmi *hdmi_drv,
54 struct hdmi_video *vpara)
56 struct hdmi_video_timing *timing = NULL;
57 struct dp_dev *dp_dev = hdmi_drv->property->priv;
58 struct dp_disp_info *disp_info = &dp_dev->disp_info;
61 if (dp_dev->early_suspended) {
62 dev_warn(hdmi_drv->dev,
63 "don't config video after dp has been suspended!\n");
67 timing = (struct hdmi_video_timing *)hdmi_vic2timing(vpara->vic);
69 dev_err(hdmi_drv->dev,
70 "[%s] not found vic %d\n", __func__, vpara->vic);
73 disp_info->mode = &timing->mode;
75 disp_info->color_depth = vpara->color_output_depth;
76 disp_info->vsync_polarity = 1;
77 disp_info->hsync_polarity = 1;
79 ret = cdn_dp_encoder_mode_set(dp_dev->dp, disp_info);
81 dev_err(hdmi_drv->dev, "dp config video mode error:%d\n", ret);
82 return HDMI_ERROR_FALSE;
88 static int rockchip_dp_detect_hotplug(struct hdmi *hdmi_drv)
90 struct dp_dev *dp_dev = hdmi_drv->property->priv;
92 if (cdn_dp_connector_detect(dp_dev->dp))
93 return HDMI_HPD_ACTIVED;
94 return HDMI_HPD_REMOVED;
97 static int rockchip_dp_read_edid(struct hdmi *hdmi_drv, int block, u8 *buf)
100 struct dp_dev *dp_dev = hdmi_drv->property->priv;
102 if (dp_dev->lanes == 4)
103 dp_dev->hdmi->property->feature |= SUPPORT_TMDS_600M;
105 dp_dev->hdmi->property->feature &= ~SUPPORT_TMDS_600M;
107 ret = cdn_dp_get_edid(dp_dev->dp, buf, block);
109 dev_err(hdmi_drv->dev, "dp config video mode error:%d\n", ret);
114 static int rockchip_dp_insert(struct hdmi *hdmi_drv)
119 static int rockchip_dp_config_vsi(struct hdmi *hdmi,
120 unsigned char vic_3d,
121 unsigned char format)
126 static void rockchip_dp_dev_init_ops(struct hdmi_ops *ops)
129 ops->disable = rockchip_dp_disable;
130 ops->enable = rockchip_dp_enable;
131 ops->remove = rockchip_dp_removed;
132 ops->setmute = rockchip_dp_control_output;
133 ops->setvideo = rockchip_dp_config_video;
134 ops->setaudio = rockchip_dp_config_audio;
135 ops->getstatus = rockchip_dp_detect_hotplug;
136 ops->getedid = rockchip_dp_read_edid;
137 ops->insert = rockchip_dp_insert;
138 ops->setvsi = rockchip_dp_config_vsi;
142 void hpd_change(struct device *dev, int lanes)
144 struct dp_dev *dp_dev = dev_get_drvdata(dev);
147 dp_dev->lanes = lanes;
149 if (dp_dev->hdmi->enable) {
150 if (dp_dev->early_suspended)
151 dev_warn(dp_dev->hdmi->dev,
152 "hpd triggered after early suspend, so don't send hpd change event !\n");
154 hdmi_submit_work(dp_dev->hdmi, HDMI_HPD_CHANGE, 10, 0);
158 static void rockchip_dp_early_suspend(struct dp_dev *dp_dev)
160 hdmi_submit_work(dp_dev->hdmi, HDMI_SUSPEND_CTL, 0, 1);
161 cdn_dp_suspend(dp_dev->dp);
164 static void rockchip_dp_early_resume(struct dp_dev *dp_dev)
166 cdn_dp_resume(dp_dev->dp);
167 hdmi_submit_work(dp_dev->hdmi, HDMI_RESUME_CTL, 0, 0);
170 static int rockchip_dp_fb_event_notify(struct notifier_block *self,
171 unsigned long action,
174 struct fb_event *event = data;
175 int blank_mode = *((int *)event->data);
176 struct dp_dev *dp_dev = container_of(self, struct dp_dev, fb_notif);
178 if (action == FB_EARLY_EVENT_BLANK) {
179 switch (blank_mode) {
180 case FB_BLANK_UNBLANK:
183 if (!dp_dev->hdmi->sleep) {
184 rockchip_dp_early_suspend(dp_dev);
185 dp_dev->early_suspended = true;
189 } else if (action == FB_EVENT_BLANK) {
190 switch (blank_mode) {
191 case FB_BLANK_UNBLANK:
192 if (dp_dev->hdmi->sleep) {
193 dp_dev->early_suspended = false;
194 rockchip_dp_early_resume(dp_dev);
205 int cdn_dp_fb_register(struct platform_device *pdev, void *dp)
207 struct hdmi_ops *rk_dp_ops;
208 struct hdmi_property *rk_cdn_dp_prop;
209 struct device *dev = &pdev->dev;
210 struct dp_dev *dp_dev;
211 struct device_node *np = dev->of_node;
214 rk_dp_ops = devm_kzalloc(dev, sizeof(struct hdmi_ops), GFP_KERNEL);
218 rk_cdn_dp_prop = devm_kzalloc(dev, sizeof(struct hdmi_property),
223 dp_dev = devm_kzalloc(dev, sizeof(struct dp_dev), GFP_KERNEL);
227 if (!of_property_read_u32(np, "dp_vop_sel", &val))
228 dp_dev->disp_info.vop_sel = val;
230 rockchip_dp_dev_init_ops(rk_dp_ops);
231 rk_cdn_dp_prop->videosrc = dp_dev->disp_info.vop_sel;
232 rk_cdn_dp_prop->display = DISPLAY_MAIN;
233 if (!of_property_read_u32(np, "dp_defaultmode", &val))
234 rk_cdn_dp_prop->defaultmode = val;
236 rk_cdn_dp_prop->defaultmode = HDMI_VIDEO_DEFAULT_MODE;
237 rk_cdn_dp_prop->name = (char *)pdev->name;
238 rk_cdn_dp_prop->priv = dp_dev;
239 rk_cdn_dp_prop->feature |=
241 SUPPORT_YCBCR_INPUT |
244 SUPPORT_RK_DISCRETE_VR;
246 if (!rk_cdn_dp_prop->videosrc) {
247 rk_cdn_dp_prop->feature |=
251 SUPPORT_YCBCR_INPUT |
255 dp_dev->hdmi = rockchip_hdmi_register(rk_cdn_dp_prop,
257 dp_dev->hdmi->dev = dev;
258 dp_dev->hdmi->enable = 1;
259 dp_dev->early_suspended = 0;
260 dp_dev->hdmi->sleep = 0;
261 dp_dev->hdmi->colormode = HDMI_COLOR_RGB_0_255;
264 dp_dev->fb_notif.notifier_call = rockchip_dp_fb_event_notify;
265 fb_register_client(&dp_dev->fb_notif);
266 dev_set_drvdata(dev, dp_dev);
268 hdmi_submit_work(dp_dev->hdmi, HDMI_HPD_CHANGE, 20, 0);