diff options
author | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2011-09-18 08:18:28 -0400 |
---|---|---|
committer | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2012-03-12 17:40:53 -0400 |
commit | 7295752fd7ec86feca6e3ccb407c1cbabf59e1d3 (patch) | |
tree | a8645bd991dd21ea78524a13ede04912464f9b7d | |
parent | ecd29947862a9a145c07098499c76c22ed5b8eb3 (diff) |
sh_mobile_hdmi: Use LCDC notification callback
Instead of accessing the LCDC channel and fb_info structures directly,
use the LCDC notification callback to inform the LCDC driver about
display-related events.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
-rw-r--r-- | drivers/video/sh_mobile_hdmi.c | 91 |
1 files changed, 14 insertions, 77 deletions
diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/sh_mobile_hdmi.c index 1464abf81a40..055cd92b85cf 100644 --- a/drivers/video/sh_mobile_hdmi.c +++ b/drivers/video/sh_mobile_hdmi.c | |||
@@ -733,12 +733,11 @@ static unsigned long sh_hdmi_rate_error(struct sh_hdmi *hdmi, | |||
733 | static int sh_hdmi_read_edid(struct sh_hdmi *hdmi, unsigned long *hdmi_rate, | 733 | static int sh_hdmi_read_edid(struct sh_hdmi *hdmi, unsigned long *hdmi_rate, |
734 | unsigned long *parent_rate) | 734 | unsigned long *parent_rate) |
735 | { | 735 | { |
736 | struct fb_info *info = hdmi->entity.lcdc | 736 | struct sh_mobile_lcdc_chan *ch = hdmi->entity.lcdc; |
737 | ? hdmi->entity.lcdc->info : NULL; | 737 | struct fb_info *info = ch ? ch->info : NULL; |
738 | struct fb_var_screeninfo tmpvar; | 738 | struct fb_var_screeninfo var; |
739 | struct fb_var_screeninfo *var = &tmpvar; | ||
740 | const struct fb_videomode *mode, *found = NULL; | 739 | const struct fb_videomode *mode, *found = NULL; |
741 | struct fb_modelist *modelist = NULL; | 740 | const struct fb_modelist *modelist = NULL; |
742 | unsigned int f_width = 0, f_height = 0, f_refresh = 0; | 741 | unsigned int f_width = 0, f_height = 0, f_refresh = 0; |
743 | unsigned long found_rate_error = ULONG_MAX; /* silly compiler... */ | 742 | unsigned long found_rate_error = ULONG_MAX; /* silly compiler... */ |
744 | bool scanning = false, preferred_bad = false; | 743 | bool scanning = false, preferred_bad = false; |
@@ -856,12 +855,10 @@ static int sh_hdmi_read_edid(struct sh_hdmi *hdmi, unsigned long *hdmi_rate, | |||
856 | } | 855 | } |
857 | 856 | ||
858 | /* Check if supported: sufficient fb memory, supported clock-rate */ | 857 | /* Check if supported: sufficient fb memory, supported clock-rate */ |
859 | fb_videomode_to_var(var, mode); | 858 | fb_videomode_to_var(&var, mode); |
860 | 859 | ||
861 | var->bits_per_pixel = info->var.bits_per_pixel; | 860 | if (ch && ch->notify && |
862 | 861 | ch->notify(ch, SH_MOBILE_LCDC_EVENT_DISPLAY_MODE, &var)) { | |
863 | if (info && info->fbops->fb_check_var && | ||
864 | info->fbops->fb_check_var(var, info)) { | ||
865 | scanning = true; | 862 | scanning = true; |
866 | preferred_bad = true; | 863 | preferred_bad = true; |
867 | continue; | 864 | continue; |
@@ -1044,32 +1041,6 @@ static const struct sh_mobile_lcdc_entity_ops sh_hdmi_ops = { | |||
1044 | .display_off = sh_hdmi_display_off, | 1041 | .display_off = sh_hdmi_display_off, |
1045 | }; | 1042 | }; |
1046 | 1043 | ||
1047 | static bool sh_hdmi_must_reconfigure(struct sh_hdmi *hdmi) | ||
1048 | { | ||
1049 | struct sh_mobile_lcdc_chan *ch = hdmi->entity.lcdc; | ||
1050 | struct fb_var_screeninfo *new_var = &hdmi->var, *old_var = &ch->display_var; | ||
1051 | struct fb_videomode mode1, mode2; | ||
1052 | |||
1053 | fb_var_to_videomode(&mode1, old_var); | ||
1054 | fb_var_to_videomode(&mode2, new_var); | ||
1055 | |||
1056 | dev_dbg(hdmi->dev, "Old %ux%u, new %ux%u\n", | ||
1057 | mode1.xres, mode1.yres, mode2.xres, mode2.yres); | ||
1058 | |||
1059 | if (fb_mode_is_equal(&mode1, &mode2)) { | ||
1060 | /* It can be a different monitor with an equal video-mode */ | ||
1061 | old_var->width = new_var->width; | ||
1062 | old_var->height = new_var->height; | ||
1063 | return false; | ||
1064 | } | ||
1065 | |||
1066 | dev_dbg(hdmi->dev, "Switching %u -> %u lines\n", | ||
1067 | mode1.yres, mode2.yres); | ||
1068 | *old_var = *new_var; | ||
1069 | |||
1070 | return true; | ||
1071 | } | ||
1072 | |||
1073 | /** | 1044 | /** |
1074 | * sh_hdmi_clk_configure() - set HDMI clock frequency and enable the clock | 1045 | * sh_hdmi_clk_configure() - set HDMI clock frequency and enable the clock |
1075 | * @hdmi: driver context | 1046 | * @hdmi: driver context |
@@ -1110,7 +1081,6 @@ static void sh_hdmi_edid_work_fn(struct work_struct *work) | |||
1110 | { | 1081 | { |
1111 | struct sh_hdmi *hdmi = container_of(work, struct sh_hdmi, edid_work.work); | 1082 | struct sh_hdmi *hdmi = container_of(work, struct sh_hdmi, edid_work.work); |
1112 | struct sh_mobile_lcdc_chan *ch = hdmi->entity.lcdc; | 1083 | struct sh_mobile_lcdc_chan *ch = hdmi->entity.lcdc; |
1113 | struct fb_info *info; | ||
1114 | int ret; | 1084 | int ret; |
1115 | 1085 | ||
1116 | dev_dbg(hdmi->dev, "%s(%p): begin, hotplug status %d\n", __func__, hdmi, | 1086 | dev_dbg(hdmi->dev, "%s(%p): begin, hotplug status %d\n", __func__, hdmi, |
@@ -1135,52 +1105,19 @@ static void sh_hdmi_edid_work_fn(struct work_struct *work) | |||
1135 | /* Switched to another (d) power-save mode */ | 1105 | /* Switched to another (d) power-save mode */ |
1136 | msleep(10); | 1106 | msleep(10); |
1137 | 1107 | ||
1138 | if (ch == NULL) | 1108 | if (ch && ch->notify) |
1139 | goto out; | 1109 | ch->notify(ch, SH_MOBILE_LCDC_EVENT_DISPLAY_CONNECT, |
1140 | 1110 | &hdmi->var); | |
1141 | info = ch->info; | ||
1142 | |||
1143 | if (lock_fb_info(info)) { | ||
1144 | console_lock(); | ||
1145 | |||
1146 | /* HDMI plug in */ | ||
1147 | if (!sh_hdmi_must_reconfigure(hdmi) && | ||
1148 | info->state == FBINFO_STATE_RUNNING) { | ||
1149 | /* | ||
1150 | * First activation with the default monitor - just turn | ||
1151 | * on, if we run a resume here, the logo disappears | ||
1152 | */ | ||
1153 | info->var.width = hdmi->var.width; | ||
1154 | info->var.height = hdmi->var.height; | ||
1155 | sh_hdmi_display_on(&hdmi->entity); | ||
1156 | } else { | ||
1157 | /* New monitor or have to wake up */ | ||
1158 | fb_set_suspend(info, 0); | ||
1159 | } | ||
1160 | |||
1161 | console_unlock(); | ||
1162 | unlock_fb_info(info); | ||
1163 | } | ||
1164 | } else { | 1111 | } else { |
1165 | ret = 0; | ||
1166 | if (ch == NULL) | ||
1167 | goto out; | ||
1168 | |||
1169 | info = ch->info; | ||
1170 | |||
1171 | hdmi->monspec.modedb_len = 0; | 1112 | hdmi->monspec.modedb_len = 0; |
1172 | fb_destroy_modedb(hdmi->monspec.modedb); | 1113 | fb_destroy_modedb(hdmi->monspec.modedb); |
1173 | hdmi->monspec.modedb = NULL; | 1114 | hdmi->monspec.modedb = NULL; |
1174 | 1115 | ||
1175 | if (lock_fb_info(info)) { | 1116 | if (ch && ch->notify) |
1176 | console_lock(); | 1117 | ch->notify(ch, SH_MOBILE_LCDC_EVENT_DISPLAY_DISCONNECT, |
1118 | NULL); | ||
1177 | 1119 | ||
1178 | /* HDMI disconnect */ | 1120 | ret = 0; |
1179 | fb_set_suspend(info, 1); | ||
1180 | |||
1181 | console_unlock(); | ||
1182 | unlock_fb_info(info); | ||
1183 | } | ||
1184 | } | 1121 | } |
1185 | 1122 | ||
1186 | out: | 1123 | out: |