~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise

« back to all changes in this revision

Viewing changes to drivers/gpu/drm/drm_fb_helper.c

  • Committer: Bazaar Package Importer
  • Author(s): Paolo Pisati
  • Date: 2011-06-29 15:23:51 UTC
  • mfrom: (26.1.1 natty-proposed)
  • Revision ID: james.westby@ubuntu.com-20110629152351-xs96tm303d95rpbk
Tags: 3.0.0-1200.2
* Rebased against 3.0.0-6.7
* BSP from TI based on 3.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
70
70
}
71
71
EXPORT_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
 
 */
86
 
static 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
 
        }
182
 
done:
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
 
 
226
73
static int drm_fb_helper_parse_command_line(struct drm_fb_helper *fb_helper)
227
74
{
228
75
        struct drm_fb_helper_connector *fb_helper_conn;
229
76
        int i;
230
77
 
231
78
        for (i = 0; i < fb_helper->connector_count; i++) {
 
79
                struct drm_cmdline_mode *mode;
 
80
                struct drm_connector *connector;
232
81
                char *option = NULL;
233
82
 
234
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
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
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
118
        return 0;
243
119
}
342
218
}
343
219
EXPORT_SYMBOL(drm_fb_helper_debug_leave);
344
220
 
 
221
bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper)
 
222
{
 
223
        bool error = false;
 
224
        int i, ret;
 
225
        for (i = 0; i < fb_helper->crtc_count; i++) {
 
226
                struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set;
 
227
                ret = drm_crtc_helper_set_config(mode_set);
 
228
                if (ret)
 
229
                        error = true;
 
230
        }
 
231
        return error;
 
232
}
 
233
EXPORT_SYMBOL(drm_fb_helper_restore_fbdev_mode);
 
234
 
345
235
bool drm_fb_helper_force_kernel_mode(void)
346
236
{
347
 
        int i = 0;
348
237
        bool ret, error = false;
349
238
        struct drm_fb_helper *helper;
350
239
 
352
241
                return false;
353
242
 
354
243
        list_for_each_entry(helper, &kernel_fb_helper_list, kernel_fb_list) {
355
 
                for (i = 0; i < helper->crtc_count; i++) {
356
 
                        struct drm_mode_set *mode_set = &helper->crtc_info[i].mode_set;
357
 
                        ret = drm_crtc_helper_set_config(mode_set);
358
 
                        if (ret)
359
 
                                error = true;
360
 
                }
 
244
                if (helper->dev->switch_power_state == DRM_SWITCH_POWER_OFF)
 
245
                        continue;
 
246
 
 
247
                ret = drm_fb_helper_restore_fbdev_mode(helper);
 
248
                if (ret)
 
249
                        error = true;
361
250
        }
362
251
        return error;
363
252
}
627
516
                value = (red << info->var.red.offset) |
628
517
                        (green << info->var.green.offset) |
629
518
                        (blue << info->var.blue.offset);
 
519
                if (info->var.transp.length > 0) {
 
520
                        u32 mask = (1 << info->var.transp.length) - 1;
 
521
                        mask <<= info->var.transp.offset;
 
522
                        value |= mask;
 
523
                }
630
524
                palette[regno] = value;
631
525
                return 0;
632
526
        }
883
777
        /* first up get a count of crtcs now in use and new min/maxes width/heights */
884
778
        for (i = 0; i < fb_helper->connector_count; i++) {
885
779
                struct drm_fb_helper_connector *fb_helper_conn = fb_helper->connector_info[i];
886
 
                struct drm_fb_helper_cmdline_mode *cmdline_mode;
 
780
                struct drm_cmdline_mode *cmdline_mode;
887
781
 
888
782
                cmdline_mode = &fb_helper_conn->cmdline_mode;
889
783
 
1105
999
 
1106
1000
static bool drm_has_cmdline_mode(struct drm_fb_helper_connector *fb_connector)
1107
1001
{
1108
 
        struct drm_fb_helper_cmdline_mode *cmdline_mode;
 
1002
        struct drm_cmdline_mode *cmdline_mode;
1109
1003
        cmdline_mode = &fb_connector->cmdline_mode;
1110
1004
        return cmdline_mode->specified;
1111
1005
}
1113
1007
static struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *fb_helper_conn,
1114
1008
                                                      int width, int height)
1115
1009
{
1116
 
        struct drm_fb_helper_cmdline_mode *cmdline_mode;
 
1010
        struct drm_cmdline_mode *cmdline_mode;
1117
1011
        struct drm_display_mode *mode = NULL;
1118
1012
 
1119
1013
        cmdline_mode = &fb_helper_conn->cmdline_mode;
1145
1039
        }
1146
1040
 
1147
1041
create_mode:
1148
 
        if (cmdline_mode->cvt)
1149
 
                mode = drm_cvt_mode(fb_helper_conn->connector->dev,
1150
 
                                    cmdline_mode->xres, cmdline_mode->yres,
1151
 
                                    cmdline_mode->refresh_specified ? cmdline_mode->refresh : 60,
1152
 
                                    cmdline_mode->rb, cmdline_mode->interlace,
1153
 
                                    cmdline_mode->margins);
1154
 
        else
1155
 
                mode = drm_gtf_mode(fb_helper_conn->connector->dev,
1156
 
                                    cmdline_mode->xres, cmdline_mode->yres,
1157
 
                                    cmdline_mode->refresh_specified ? cmdline_mode->refresh : 60,
1158
 
                                    cmdline_mode->interlace,
1159
 
                                    cmdline_mode->margins);
1160
 
        drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
 
1042
        mode = drm_mode_create_from_cmdline_mode(fb_helper_conn->connector->dev,
 
1043
                                                 cmdline_mode);
1161
1044
        list_add(&mode->head, &fb_helper_conn->connector->modes);
1162
1045
        return mode;
1163
1046
}
1498
1381
}
1499
1382
EXPORT_SYMBOL(drm_fb_helper_initial_config);
1500
1383
 
1501
 
bool drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
 
1384
/**
 
1385
 * drm_fb_helper_hotplug_event - respond to a hotplug notification by
 
1386
 *                               probing all the outputs attached to the fb.
 
1387
 * @fb_helper: the drm_fb_helper
 
1388
 *
 
1389
 * LOCKING:
 
1390
 * Called at runtime, must take mode config lock.
 
1391
 *
 
1392
 * Scan the connectors attached to the fb_helper and try to put together a
 
1393
 * setup after *notification of a change in output configuration.
 
1394
 *
 
1395
 * RETURNS:
 
1396
 * 0 on success and a non-zero error code otherwise.
 
1397
 */
 
1398
int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
1502
1399
{
 
1400
        struct drm_device *dev = fb_helper->dev;
1503
1401
        int count = 0;
1504
1402
        u32 max_width, max_height, bpp_sel;
1505
1403
        bool bound = false, crtcs_bound = false;
1506
1404
        struct drm_crtc *crtc;
1507
1405
 
1508
1406
        if (!fb_helper->fb)
1509
 
                return false;
 
1407
                return 0;
1510
1408
 
1511
 
        list_for_each_entry(crtc, &fb_helper->dev->mode_config.crtc_list, head) {
 
1409
        mutex_lock(&dev->mode_config.mutex);
 
1410
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
1512
1411
                if (crtc->fb)
1513
1412
                        crtcs_bound = true;
1514
1413
                if (crtc->fb == fb_helper->fb)
1517
1416
 
1518
1417
        if (!bound && crtcs_bound) {
1519
1418
                fb_helper->delayed_hotplug = true;
1520
 
                return false;
 
1419
                mutex_unlock(&dev->mode_config.mutex);
 
1420
                return 0;
1521
1421
        }
1522
1422
        DRM_DEBUG_KMS("\n");
1523
1423
 
1528
1428
        count = drm_fb_helper_probe_connector_modes(fb_helper, max_width,
1529
1429
                                                    max_height);
1530
1430
        drm_setup_crtcs(fb_helper);
 
1431
        mutex_unlock(&dev->mode_config.mutex);
1531
1432
 
1532
1433
        return drm_fb_helper_single_fb_probe(fb_helper, bpp_sel);
1533
1434
}