aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/powerpc/dts-bindings/fsl/diu.txt6
-rw-r--r--drivers/video/Kconfig1
-rw-r--r--drivers/video/fsl-diu-fb.c80
3 files changed, 81 insertions, 6 deletions
diff --git a/Documentation/powerpc/dts-bindings/fsl/diu.txt b/Documentation/powerpc/dts-bindings/fsl/diu.txt
index 326cddfd7c25..b66cb6d31d69 100644
--- a/Documentation/powerpc/dts-bindings/fsl/diu.txt
+++ b/Documentation/powerpc/dts-bindings/fsl/diu.txt
@@ -11,6 +11,11 @@ Required properties:
11- interrupt-parent : the phandle for the interrupt controller that 11- interrupt-parent : the phandle for the interrupt controller that
12 services interrupts for this device. 12 services interrupts for this device.
13 13
14Optional properties:
15- edid : verbatim EDID data block describing attached display.
16 Data from the detailed timing descriptor will be used to
17 program the display controller.
18
14Example (MPC8610HPCD): 19Example (MPC8610HPCD):
15 display@2c000 { 20 display@2c000 {
16 compatible = "fsl,diu"; 21 compatible = "fsl,diu";
@@ -25,4 +30,5 @@ Example for MPC5121:
25 reg = <0x2100 0x100>; 30 reg = <0x2100 0x100>;
26 interrupts = <64 0x8>; 31 interrupts = <64 0x8>;
27 interrupt-parent = <&ipic>; 32 interrupt-parent = <&ipic>;
33 edid = [edid-data];
28 }; 34 };
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 3d94a1471724..114aeb0d9971 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -1871,6 +1871,7 @@ config FB_MBX_DEBUG
1871config FB_FSL_DIU 1871config FB_FSL_DIU
1872 tristate "Freescale DIU framebuffer support" 1872 tristate "Freescale DIU framebuffer support"
1873 depends on FB && FSL_SOC 1873 depends on FB && FSL_SOC
1874 select FB_MODE_HELPERS
1874 select FB_CFB_FILLRECT 1875 select FB_CFB_FILLRECT
1875 select FB_CFB_COPYAREA 1876 select FB_CFB_COPYAREA
1876 select FB_CFB_IMAGEBLIT 1877 select FB_CFB_IMAGEBLIT
diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c
index db3e360e6aad..e38ad2224540 100644
--- a/drivers/video/fsl-diu-fb.c
+++ b/drivers/video/fsl-diu-fb.c
@@ -35,6 +35,7 @@
35 35
36#include <sysdev/fsl_soc.h> 36#include <sysdev/fsl_soc.h>
37#include <linux/fsl-diu-fb.h> 37#include <linux/fsl-diu-fb.h>
38#include "edid.h"
38 39
39/* 40/*
40 * These parameters give default parameters 41 * These parameters give default parameters
@@ -217,6 +218,7 @@ struct mfb_info {
217 int x_aoi_d; /* aoi display x offset to physical screen */ 218 int x_aoi_d; /* aoi display x offset to physical screen */
218 int y_aoi_d; /* aoi display y offset to physical screen */ 219 int y_aoi_d; /* aoi display y offset to physical screen */
219 struct fsl_diu_data *parent; 220 struct fsl_diu_data *parent;
221 u8 *edid_data;
220}; 222};
221 223
222 224
@@ -1185,18 +1187,30 @@ static int __devinit install_fb(struct fb_info *info)
1185 int rc; 1187 int rc;
1186 struct mfb_info *mfbi = info->par; 1188 struct mfb_info *mfbi = info->par;
1187 const char *aoi_mode, *init_aoi_mode = "320x240"; 1189 const char *aoi_mode, *init_aoi_mode = "320x240";
1190 struct fb_videomode *db = fsl_diu_mode_db;
1191 unsigned int dbsize = ARRAY_SIZE(fsl_diu_mode_db);
1192 int has_default_mode = 1;
1188 1193
1189 if (init_fbinfo(info)) 1194 if (init_fbinfo(info))
1190 return -EINVAL; 1195 return -EINVAL;
1191 1196
1192 if (mfbi->index == 0) /* plane 0 */ 1197 if (mfbi->index == 0) { /* plane 0 */
1198 if (mfbi->edid_data) {
1199 /* Now build modedb from EDID */
1200 fb_edid_to_monspecs(mfbi->edid_data, &info->monspecs);
1201 fb_videomode_to_modelist(info->monspecs.modedb,
1202 info->monspecs.modedb_len,
1203 &info->modelist);
1204 db = info->monspecs.modedb;
1205 dbsize = info->monspecs.modedb_len;
1206 }
1193 aoi_mode = fb_mode; 1207 aoi_mode = fb_mode;
1194 else 1208 } else {
1195 aoi_mode = init_aoi_mode; 1209 aoi_mode = init_aoi_mode;
1210 }
1196 pr_debug("mode used = %s\n", aoi_mode); 1211 pr_debug("mode used = %s\n", aoi_mode);
1197 rc = fb_find_mode(&info->var, info, aoi_mode, fsl_diu_mode_db, 1212 rc = fb_find_mode(&info->var, info, aoi_mode, db, dbsize,
1198 ARRAY_SIZE(fsl_diu_mode_db), &fsl_diu_default_mode, default_bpp); 1213 &fsl_diu_default_mode, default_bpp);
1199
1200 switch (rc) { 1214 switch (rc) {
1201 case 1: 1215 case 1:
1202 pr_debug("using mode specified in @mode\n"); 1216 pr_debug("using mode specified in @mode\n");
@@ -1214,10 +1228,50 @@ static int __devinit install_fb(struct fb_info *info)
1214 default: 1228 default:
1215 pr_debug("rc = %d\n", rc); 1229 pr_debug("rc = %d\n", rc);
1216 pr_debug("failed to find mode\n"); 1230 pr_debug("failed to find mode\n");
1217 return -EINVAL; 1231 /*
1232 * For plane 0 we continue and look into
1233 * driver's internal modedb.
1234 */
1235 if (mfbi->index == 0 && mfbi->edid_data)
1236 has_default_mode = 0;
1237 else
1238 return -EINVAL;
1218 break; 1239 break;
1219 } 1240 }
1220 1241
1242 if (!has_default_mode) {
1243 rc = fb_find_mode(&info->var, info, aoi_mode, fsl_diu_mode_db,
1244 ARRAY_SIZE(fsl_diu_mode_db),
1245 &fsl_diu_default_mode,
1246 default_bpp);
1247 if (rc > 0 && rc < 5)
1248 has_default_mode = 1;
1249 }
1250
1251 /* Still not found, use preferred mode from database if any */
1252 if (!has_default_mode && info->monspecs.modedb) {
1253 struct fb_monspecs *specs = &info->monspecs;
1254 struct fb_videomode *modedb = &specs->modedb[0];
1255
1256 /*
1257 * Get preferred timing. If not found,
1258 * first mode in database will be used.
1259 */
1260 if (specs->misc & FB_MISC_1ST_DETAIL) {
1261 int i;
1262
1263 for (i = 0; i < specs->modedb_len; i++) {
1264 if (specs->modedb[i].flag & FB_MODE_IS_FIRST) {
1265 modedb = &specs->modedb[i];
1266 break;
1267 }
1268 }
1269 }
1270
1271 info->var.bits_per_pixel = default_bpp;
1272 fb_videomode_to_var(&info->var, modedb);
1273 }
1274
1221 pr_debug("xres_virtual %d\n", info->var.xres_virtual); 1275 pr_debug("xres_virtual %d\n", info->var.xres_virtual);
1222 pr_debug("bits_per_pixel %d\n", info->var.bits_per_pixel); 1276 pr_debug("bits_per_pixel %d\n", info->var.bits_per_pixel);
1223 1277
@@ -1256,6 +1310,9 @@ static void uninstall_fb(struct fb_info *info)
1256 if (!mfbi->registered) 1310 if (!mfbi->registered)
1257 return; 1311 return;
1258 1312
1313 if (mfbi->index == 0)
1314 kfree(mfbi->edid_data);
1315
1259 unregister_framebuffer(info); 1316 unregister_framebuffer(info);
1260 unmap_video_memory(info); 1317 unmap_video_memory(info);
1261 if (&info->cmap) 1318 if (&info->cmap)
@@ -1456,6 +1513,17 @@ static int __devinit fsl_diu_probe(struct of_device *ofdev,
1456 mfbi = machine_data->fsl_diu_info[i]->par; 1513 mfbi = machine_data->fsl_diu_info[i]->par;
1457 memcpy(mfbi, &mfb_template[i], sizeof(struct mfb_info)); 1514 memcpy(mfbi, &mfb_template[i], sizeof(struct mfb_info));
1458 mfbi->parent = machine_data; 1515 mfbi->parent = machine_data;
1516
1517 if (mfbi->index == 0) {
1518 const u8 *prop;
1519 int len;
1520
1521 /* Get EDID */
1522 prop = of_get_property(np, "edid", &len);
1523 if (prop && len == EDID_LENGTH)
1524 mfbi->edid_data = kmemdup(prop, EDID_LENGTH,
1525 GFP_KERNEL);
1526 }
1459 } 1527 }
1460 1528
1461 ret = of_address_to_resource(np, 0, &res); 1529 ret = of_address_to_resource(np, 0, &res);