aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_fb_helper.c
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2011-04-17 02:43:32 -0400
committerDave Airlie <airlied@redhat.com>2011-04-28 00:56:23 -0400
commit1794d257fa7bab3ea5162f8abdca749996b65343 (patch)
treeea8d035a218a0cb0ee83443b3c25bd8df25567e2 /drivers/gpu/drm/drm_fb_helper.c
parentbbb0aef5cfe95fe9b51a7eeba4a440b69037b01f (diff)
drm: Export the command-line mode parser
In the absence of configuration data for providing the fixed mode for a panel, I would like to be able to pass such modes along a separate module paramenter. To do so, I then need to parse a modeline from a string, which drm is already capable of. Export that capability to the drivers. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/drm_fb_helper.c')
-rw-r--r--drivers/gpu/drm/drm_fb_helper.c207
1 files changed, 36 insertions, 171 deletions
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 140b9525b48a..802b61ac3139 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -70,174 +70,50 @@ fail:
70} 70}
71EXPORT_SYMBOL(drm_fb_helper_single_add_all_connectors); 71EXPORT_SYMBOL(drm_fb_helper_single_add_all_connectors);
72 72
73/**
74 * drm_fb_helper_connector_parse_command_line - parse command line for connector
75 * @connector - connector to parse line for
76 * @mode_option - per connector mode option
77 *
78 * This parses the connector specific then generic command lines for
79 * modes and options to configure the connector.
80 *
81 * This uses the same parameters as the fb modedb.c, except for extra
82 * <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m][eDd]
83 *
84 * enable/enable Digital/disable bit at the end
85 */
86static bool drm_fb_helper_connector_parse_command_line(struct drm_fb_helper_connector *fb_helper_conn,
87 const char *mode_option)
88{
89 const char *name;
90 unsigned int namelen;
91 int res_specified = 0, bpp_specified = 0, refresh_specified = 0;
92 unsigned int xres = 0, yres = 0, bpp = 32, refresh = 0;
93 int yres_specified = 0, cvt = 0, rb = 0, interlace = 0, margins = 0;
94 int i;
95 enum drm_connector_force force = DRM_FORCE_UNSPECIFIED;
96 struct drm_fb_helper_cmdline_mode *cmdline_mode;
97 struct drm_connector *connector;
98
99 if (!fb_helper_conn)
100 return false;
101 connector = fb_helper_conn->connector;
102
103 cmdline_mode = &fb_helper_conn->cmdline_mode;
104 if (!mode_option)
105 mode_option = fb_mode_option;
106
107 if (!mode_option) {
108 cmdline_mode->specified = false;
109 return false;
110 }
111
112 name = mode_option;
113 namelen = strlen(name);
114 for (i = namelen-1; i >= 0; i--) {
115 switch (name[i]) {
116 case '@':
117 namelen = i;
118 if (!refresh_specified && !bpp_specified &&
119 !yres_specified) {
120 refresh = simple_strtol(&name[i+1], NULL, 10);
121 refresh_specified = 1;
122 if (cvt || rb)
123 cvt = 0;
124 } else
125 goto done;
126 break;
127 case '-':
128 namelen = i;
129 if (!bpp_specified && !yres_specified) {
130 bpp = simple_strtol(&name[i+1], NULL, 10);
131 bpp_specified = 1;
132 if (cvt || rb)
133 cvt = 0;
134 } else
135 goto done;
136 break;
137 case 'x':
138 if (!yres_specified) {
139 yres = simple_strtol(&name[i+1], NULL, 10);
140 yres_specified = 1;
141 } else
142 goto done;
143 case '0' ... '9':
144 break;
145 case 'M':
146 if (!yres_specified)
147 cvt = 1;
148 break;
149 case 'R':
150 if (cvt)
151 rb = 1;
152 break;
153 case 'm':
154 if (!cvt)
155 margins = 1;
156 break;
157 case 'i':
158 if (!cvt)
159 interlace = 1;
160 break;
161 case 'e':
162 force = DRM_FORCE_ON;
163 break;
164 case 'D':
165 if ((connector->connector_type != DRM_MODE_CONNECTOR_DVII) &&
166 (connector->connector_type != DRM_MODE_CONNECTOR_HDMIB))
167 force = DRM_FORCE_ON;
168 else
169 force = DRM_FORCE_ON_DIGITAL;
170 break;
171 case 'd':
172 force = DRM_FORCE_OFF;
173 break;
174 default:
175 goto done;
176 }
177 }
178 if (i < 0 && yres_specified) {
179 xres = simple_strtol(name, NULL, 10);
180 res_specified = 1;
181 }
182done:
183
184 DRM_DEBUG_KMS("cmdline mode for connector %s %dx%d@%dHz%s%s%s\n",
185 drm_get_connector_name(connector), xres, yres,
186 (refresh) ? refresh : 60, (rb) ? " reduced blanking" :
187 "", (margins) ? " with margins" : "", (interlace) ?
188 " interlaced" : "");
189
190 if (force) {
191 const char *s;
192 switch (force) {
193 case DRM_FORCE_OFF: s = "OFF"; break;
194 case DRM_FORCE_ON_DIGITAL: s = "ON - dig"; break;
195 default:
196 case DRM_FORCE_ON: s = "ON"; break;
197 }
198
199 DRM_INFO("forcing %s connector %s\n",
200 drm_get_connector_name(connector), s);
201 connector->force = force;
202 }
203
204 if (res_specified) {
205 cmdline_mode->specified = true;
206 cmdline_mode->xres = xres;
207 cmdline_mode->yres = yres;
208 }
209
210 if (refresh_specified) {
211 cmdline_mode->refresh_specified = true;
212 cmdline_mode->refresh = refresh;
213 }
214
215 if (bpp_specified) {
216 cmdline_mode->bpp_specified = true;
217 cmdline_mode->bpp = bpp;
218 }
219 cmdline_mode->rb = rb ? true : false;
220 cmdline_mode->cvt = cvt ? true : false;
221 cmdline_mode->interlace = interlace ? true : false;
222
223 return true;
224}
225
226static int drm_fb_helper_parse_command_line(struct drm_fb_helper *fb_helper) 73static int drm_fb_helper_parse_command_line(struct drm_fb_helper *fb_helper)
227{ 74{
228 struct drm_fb_helper_connector *fb_helper_conn; 75 struct drm_fb_helper_connector *fb_helper_conn;
229 int i; 76 int i;
230 77
231 for (i = 0; i < fb_helper->connector_count; i++) { 78 for (i = 0; i < fb_helper->connector_count; i++) {
79 struct drm_cmdline_mode *mode;
80 struct drm_connector *connector;
232 char *option = NULL; 81 char *option = NULL;
233 82
234 fb_helper_conn = fb_helper->connector_info[i]; 83 fb_helper_conn = fb_helper->connector_info[i];
84 connector = fb_helper_conn->connector;
85 mode = &fb_helper_conn->cmdline_mode;
235 86
236 /* do something on return - turn off connector maybe */ 87 /* do something on return - turn off connector maybe */
237 if (fb_get_options(drm_get_connector_name(fb_helper_conn->connector), &option)) 88 if (fb_get_options(drm_get_connector_name(connector), &option))
238 continue; 89 continue;
239 90
240 drm_fb_helper_connector_parse_command_line(fb_helper_conn, option); 91 if (drm_mode_parse_command_line_for_connector(option,
92 connector,
93 mode)) {
94 if (mode->force) {
95 const char *s;
96 switch (mode->force) {
97 case DRM_FORCE_OFF: s = "OFF"; break;
98 case DRM_FORCE_ON_DIGITAL: s = "ON - dig"; break;
99 default:
100 case DRM_FORCE_ON: s = "ON"; break;
101 }
102
103 DRM_INFO("forcing %s connector %s\n",
104 drm_get_connector_name(connector), s);
105 connector->force = mode->force;
106 }
107
108 DRM_DEBUG_KMS("cmdline mode for connector %s %dx%d@%dHz%s%s%s\n",
109 drm_get_connector_name(connector),
110 mode->xres, mode->yres,
111 mode->refresh_specified ? mode->refresh : 60,
112 mode->rb ? " reduced blanking" : "",
113 mode->margins ? " with margins" : "",
114 mode->interlace ? " interlaced" : "");
115 }
116
241 } 117 }
242 return 0; 118 return 0;
243} 119}
@@ -901,7 +777,7 @@ int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
901 /* first up get a count of crtcs now in use and new min/maxes width/heights */ 777 /* first up get a count of crtcs now in use and new min/maxes width/heights */
902 for (i = 0; i < fb_helper->connector_count; i++) { 778 for (i = 0; i < fb_helper->connector_count; i++) {
903 struct drm_fb_helper_connector *fb_helper_conn = fb_helper->connector_info[i]; 779 struct drm_fb_helper_connector *fb_helper_conn = fb_helper->connector_info[i];
904 struct drm_fb_helper_cmdline_mode *cmdline_mode; 780 struct drm_cmdline_mode *cmdline_mode;
905 781
906 cmdline_mode = &fb_helper_conn->cmdline_mode; 782 cmdline_mode = &fb_helper_conn->cmdline_mode;
907 783
@@ -1123,7 +999,7 @@ static struct drm_display_mode *drm_has_preferred_mode(struct drm_fb_helper_conn
1123 999
1124static bool drm_has_cmdline_mode(struct drm_fb_helper_connector *fb_connector) 1000static bool drm_has_cmdline_mode(struct drm_fb_helper_connector *fb_connector)
1125{ 1001{
1126 struct drm_fb_helper_cmdline_mode *cmdline_mode; 1002 struct drm_cmdline_mode *cmdline_mode;
1127 cmdline_mode = &fb_connector->cmdline_mode; 1003 cmdline_mode = &fb_connector->cmdline_mode;
1128 return cmdline_mode->specified; 1004 return cmdline_mode->specified;
1129} 1005}
@@ -1131,7 +1007,7 @@ static bool drm_has_cmdline_mode(struct drm_fb_helper_connector *fb_connector)
1131static struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn, 1007static struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn,
1132 int width, int height) 1008 int width, int height)
1133{ 1009{
1134 struct drm_fb_helper_cmdline_mode *cmdline_mode; 1010 struct drm_cmdline_mode *cmdline_mode;
1135 struct drm_display_mode *mode = NULL; 1011 struct drm_display_mode *mode = NULL;
1136 1012
1137 cmdline_mode = &fb_helper_conn->cmdline_mode; 1013 cmdline_mode = &fb_helper_conn->cmdline_mode;
@@ -1163,19 +1039,8 @@ static struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_conne
1163 } 1039 }
1164 1040
1165create_mode: 1041create_mode:
1166 if (cmdline_mode->cvt) 1042 mode = drm_mode_create_from_cmdline_mode(fb_helper_conn->connector->dev,
1167 mode = drm_cvt_mode(fb_helper_conn->connector->dev, 1043 cmdline_mode);
1168 cmdline_mode->xres, cmdline_mode->yres,
1169 cmdline_mode->refresh_specified ? cmdline_mode->refresh : 60,
1170 cmdline_mode->rb, cmdline_mode->interlace,
1171 cmdline_mode->margins);
1172 else
1173 mode = drm_gtf_mode(fb_helper_conn->connector->dev,
1174 cmdline_mode->xres, cmdline_mode->yres,
1175 cmdline_mode->refresh_specified ? cmdline_mode->refresh : 60,
1176 cmdline_mode->interlace,
1177 cmdline_mode->margins);
1178 drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
1179 list_add(&mode->head, &fb_helper_conn->connector->modes); 1044 list_add(&mode->head, &fb_helper_conn->connector->modes);
1180 return mode; 1045 return mode;
1181} 1046}