|
@@ -1211,154 +1211,180 @@ static struct pxafb_info * __init pxafb_init_fbinfo(struct device *dev)
|
|
|
}
|
|
|
|
|
|
#ifdef CONFIG_FB_PXA_PARAMETERS
|
|
|
-static int __init pxafb_parse_options(struct device *dev, char *options)
|
|
|
+static int parse_opt_mode(struct device *dev, const char *this_opt)
|
|
|
{
|
|
|
struct pxafb_mach_info *inf = dev->platform_data;
|
|
|
+
|
|
|
+ const char *name = this_opt+5;
|
|
|
+ unsigned int namelen = strlen(name);
|
|
|
+ int res_specified = 0, bpp_specified = 0;
|
|
|
+ unsigned int xres = 0, yres = 0, bpp = 0;
|
|
|
+ int yres_specified = 0;
|
|
|
+ int i;
|
|
|
+ for (i = namelen-1; i >= 0; i--) {
|
|
|
+ switch (name[i]) {
|
|
|
+ case '-':
|
|
|
+ namelen = i;
|
|
|
+ if (!bpp_specified && !yres_specified) {
|
|
|
+ bpp = simple_strtoul(&name[i+1], NULL, 0);
|
|
|
+ bpp_specified = 1;
|
|
|
+ } else
|
|
|
+ goto done;
|
|
|
+ break;
|
|
|
+ case 'x':
|
|
|
+ if (!yres_specified) {
|
|
|
+ yres = simple_strtoul(&name[i+1], NULL, 0);
|
|
|
+ yres_specified = 1;
|
|
|
+ } else
|
|
|
+ goto done;
|
|
|
+ break;
|
|
|
+ case '0' ... '9':
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ goto done;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (i < 0 && yres_specified) {
|
|
|
+ xres = simple_strtoul(name, NULL, 0);
|
|
|
+ res_specified = 1;
|
|
|
+ }
|
|
|
+done:
|
|
|
+ if (res_specified) {
|
|
|
+ dev_info(dev, "overriding resolution: %dx%d\n", xres, yres);
|
|
|
+ inf->modes[0].xres = xres; inf->modes[0].yres = yres;
|
|
|
+ }
|
|
|
+ if (bpp_specified)
|
|
|
+ switch (bpp) {
|
|
|
+ case 1:
|
|
|
+ case 2:
|
|
|
+ case 4:
|
|
|
+ case 8:
|
|
|
+ case 16:
|
|
|
+ inf->modes[0].bpp = bpp;
|
|
|
+ dev_info(dev, "overriding bit depth: %d\n", bpp);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ dev_err(dev, "Depth %d is not valid\n", bpp);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int parse_opt(struct device *dev, char *this_opt)
|
|
|
+{
|
|
|
+ struct pxafb_mach_info *inf = dev->platform_data;
|
|
|
+ struct pxafb_mode_info *mode = &inf->modes[0];
|
|
|
+ char s[64];
|
|
|
+
|
|
|
+ s[0] = '\0';
|
|
|
+
|
|
|
+ if (!strncmp(this_opt, "mode:", 5)) {
|
|
|
+ return parse_opt_mode(dev, this_opt);
|
|
|
+ } else if (!strncmp(this_opt, "pixclock:", 9)) {
|
|
|
+ mode->pixclock = simple_strtoul(this_opt+9, NULL, 0);
|
|
|
+ sprintf(s, "pixclock: %ld\n", mode->pixclock);
|
|
|
+ } else if (!strncmp(this_opt, "left:", 5)) {
|
|
|
+ mode->left_margin = simple_strtoul(this_opt+5, NULL, 0);
|
|
|
+ sprintf(s, "left: %u\n", mode->left_margin);
|
|
|
+ } else if (!strncmp(this_opt, "right:", 6)) {
|
|
|
+ mode->right_margin = simple_strtoul(this_opt+6, NULL, 0);
|
|
|
+ sprintf(s, "right: %u\n", mode->right_margin);
|
|
|
+ } else if (!strncmp(this_opt, "upper:", 6)) {
|
|
|
+ mode->upper_margin = simple_strtoul(this_opt+6, NULL, 0);
|
|
|
+ sprintf(s, "upper: %u\n", mode->upper_margin);
|
|
|
+ } else if (!strncmp(this_opt, "lower:", 6)) {
|
|
|
+ mode->lower_margin = simple_strtoul(this_opt+6, NULL, 0);
|
|
|
+ sprintf(s, "lower: %u\n", mode->lower_margin);
|
|
|
+ } else if (!strncmp(this_opt, "hsynclen:", 9)) {
|
|
|
+ mode->hsync_len = simple_strtoul(this_opt+9, NULL, 0);
|
|
|
+ sprintf(s, "hsynclen: %u\n", mode->hsync_len);
|
|
|
+ } else if (!strncmp(this_opt, "vsynclen:", 9)) {
|
|
|
+ mode->vsync_len = simple_strtoul(this_opt+9, NULL, 0);
|
|
|
+ sprintf(s, "vsynclen: %u\n", mode->vsync_len);
|
|
|
+ } else if (!strncmp(this_opt, "hsync:", 6)) {
|
|
|
+ if (simple_strtoul(this_opt+6, NULL, 0) == 0) {
|
|
|
+ sprintf(s, "hsync: Active Low\n");
|
|
|
+ mode->sync &= ~FB_SYNC_HOR_HIGH_ACT;
|
|
|
+ } else {
|
|
|
+ sprintf(s, "hsync: Active High\n");
|
|
|
+ mode->sync |= FB_SYNC_HOR_HIGH_ACT;
|
|
|
+ }
|
|
|
+ } else if (!strncmp(this_opt, "vsync:", 6)) {
|
|
|
+ if (simple_strtoul(this_opt+6, NULL, 0) == 0) {
|
|
|
+ sprintf(s, "vsync: Active Low\n");
|
|
|
+ mode->sync &= ~FB_SYNC_VERT_HIGH_ACT;
|
|
|
+ } else {
|
|
|
+ sprintf(s, "vsync: Active High\n");
|
|
|
+ mode->sync |= FB_SYNC_VERT_HIGH_ACT;
|
|
|
+ }
|
|
|
+ } else if (!strncmp(this_opt, "dpc:", 4)) {
|
|
|
+ if (simple_strtoul(this_opt+4, NULL, 0) == 0) {
|
|
|
+ sprintf(s, "double pixel clock: false\n");
|
|
|
+ inf->lccr3 &= ~LCCR3_DPC;
|
|
|
+ } else {
|
|
|
+ sprintf(s, "double pixel clock: true\n");
|
|
|
+ inf->lccr3 |= LCCR3_DPC;
|
|
|
+ }
|
|
|
+ } else if (!strncmp(this_opt, "outputen:", 9)) {
|
|
|
+ if (simple_strtoul(this_opt+9, NULL, 0) == 0) {
|
|
|
+ sprintf(s, "output enable: active low\n");
|
|
|
+ inf->lccr3 = (inf->lccr3 & ~LCCR3_OEP) | LCCR3_OutEnL;
|
|
|
+ } else {
|
|
|
+ sprintf(s, "output enable: active high\n");
|
|
|
+ inf->lccr3 = (inf->lccr3 & ~LCCR3_OEP) | LCCR3_OutEnH;
|
|
|
+ }
|
|
|
+ } else if (!strncmp(this_opt, "pixclockpol:", 12)) {
|
|
|
+ if (simple_strtoul(this_opt+12, NULL, 0) == 0) {
|
|
|
+ sprintf(s, "pixel clock polarity: falling edge\n");
|
|
|
+ inf->lccr3 = (inf->lccr3 & ~LCCR3_PCP) | LCCR3_PixFlEdg;
|
|
|
+ } else {
|
|
|
+ sprintf(s, "pixel clock polarity: rising edge\n");
|
|
|
+ inf->lccr3 = (inf->lccr3 & ~LCCR3_PCP) | LCCR3_PixRsEdg;
|
|
|
+ }
|
|
|
+ } else if (!strncmp(this_opt, "color", 5)) {
|
|
|
+ inf->lccr0 = (inf->lccr0 & ~LCCR0_CMS) | LCCR0_Color;
|
|
|
+ } else if (!strncmp(this_opt, "mono", 4)) {
|
|
|
+ inf->lccr0 = (inf->lccr0 & ~LCCR0_CMS) | LCCR0_Mono;
|
|
|
+ } else if (!strncmp(this_opt, "active", 6)) {
|
|
|
+ inf->lccr0 = (inf->lccr0 & ~LCCR0_PAS) | LCCR0_Act;
|
|
|
+ } else if (!strncmp(this_opt, "passive", 7)) {
|
|
|
+ inf->lccr0 = (inf->lccr0 & ~LCCR0_PAS) | LCCR0_Pas;
|
|
|
+ } else if (!strncmp(this_opt, "single", 6)) {
|
|
|
+ inf->lccr0 = (inf->lccr0 & ~LCCR0_SDS) | LCCR0_Sngl;
|
|
|
+ } else if (!strncmp(this_opt, "dual", 4)) {
|
|
|
+ inf->lccr0 = (inf->lccr0 & ~LCCR0_SDS) | LCCR0_Dual;
|
|
|
+ } else if (!strncmp(this_opt, "4pix", 4)) {
|
|
|
+ inf->lccr0 = (inf->lccr0 & ~LCCR0_DPD) | LCCR0_4PixMono;
|
|
|
+ } else if (!strncmp(this_opt, "8pix", 4)) {
|
|
|
+ inf->lccr0 = (inf->lccr0 & ~LCCR0_DPD) | LCCR0_8PixMono;
|
|
|
+ } else {
|
|
|
+ dev_err(dev, "unknown option: %s\n", this_opt);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (s[0] != '\0')
|
|
|
+ dev_info(dev, "override %s", s);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int __init pxafb_parse_options(struct device *dev, char *options)
|
|
|
+{
|
|
|
char *this_opt;
|
|
|
+ int ret;
|
|
|
|
|
|
- if (!options || !*options)
|
|
|
- return 0;
|
|
|
+ if (!options || !*options)
|
|
|
+ return 0;
|
|
|
|
|
|
dev_dbg(dev, "options are \"%s\"\n", options ? options : "null");
|
|
|
|
|
|
/* could be made table driven or similar?... */
|
|
|
- while ((this_opt = strsep(&options, ",")) != NULL) {
|
|
|
- if (!strncmp(this_opt, "mode:", 5)) {
|
|
|
- const char *name = this_opt+5;
|
|
|
- unsigned int namelen = strlen(name);
|
|
|
- int res_specified = 0, bpp_specified = 0;
|
|
|
- unsigned int xres = 0, yres = 0, bpp = 0;
|
|
|
- int yres_specified = 0;
|
|
|
- int i;
|
|
|
- for (i = namelen-1; i >= 0; i--) {
|
|
|
- switch (name[i]) {
|
|
|
- case '-':
|
|
|
- namelen = i;
|
|
|
- if (!bpp_specified && !yres_specified) {
|
|
|
- bpp = simple_strtoul(&name[i+1], NULL, 0);
|
|
|
- bpp_specified = 1;
|
|
|
- } else
|
|
|
- goto done;
|
|
|
- break;
|
|
|
- case 'x':
|
|
|
- if (!yres_specified) {
|
|
|
- yres = simple_strtoul(&name[i+1], NULL, 0);
|
|
|
- yres_specified = 1;
|
|
|
- } else
|
|
|
- goto done;
|
|
|
- break;
|
|
|
- case '0' ... '9':
|
|
|
- break;
|
|
|
- default:
|
|
|
- goto done;
|
|
|
- }
|
|
|
- }
|
|
|
- if (i < 0 && yres_specified) {
|
|
|
- xres = simple_strtoul(name, NULL, 0);
|
|
|
- res_specified = 1;
|
|
|
- }
|
|
|
- done:
|
|
|
- if (res_specified) {
|
|
|
- dev_info(dev, "overriding resolution: %dx%d\n", xres, yres);
|
|
|
- inf->modes[0].xres = xres; inf->modes[0].yres = yres;
|
|
|
- }
|
|
|
- if (bpp_specified)
|
|
|
- switch (bpp) {
|
|
|
- case 1:
|
|
|
- case 2:
|
|
|
- case 4:
|
|
|
- case 8:
|
|
|
- case 16:
|
|
|
- inf->modes[0].bpp = bpp;
|
|
|
- dev_info(dev, "overriding bit depth: %d\n", bpp);
|
|
|
- break;
|
|
|
- default:
|
|
|
- dev_err(dev, "Depth %d is not valid\n", bpp);
|
|
|
- }
|
|
|
- } else if (!strncmp(this_opt, "pixclock:", 9)) {
|
|
|
- inf->modes[0].pixclock = simple_strtoul(this_opt+9, NULL, 0);
|
|
|
- dev_info(dev, "override pixclock: %ld\n", inf->modes[0].pixclock);
|
|
|
- } else if (!strncmp(this_opt, "left:", 5)) {
|
|
|
- inf->modes[0].left_margin = simple_strtoul(this_opt+5, NULL, 0);
|
|
|
- dev_info(dev, "override left: %u\n", inf->modes[0].left_margin);
|
|
|
- } else if (!strncmp(this_opt, "right:", 6)) {
|
|
|
- inf->modes[0].right_margin = simple_strtoul(this_opt+6, NULL, 0);
|
|
|
- dev_info(dev, "override right: %u\n", inf->modes[0].right_margin);
|
|
|
- } else if (!strncmp(this_opt, "upper:", 6)) {
|
|
|
- inf->modes[0].upper_margin = simple_strtoul(this_opt+6, NULL, 0);
|
|
|
- dev_info(dev, "override upper: %u\n", inf->modes[0].upper_margin);
|
|
|
- } else if (!strncmp(this_opt, "lower:", 6)) {
|
|
|
- inf->modes[0].lower_margin = simple_strtoul(this_opt+6, NULL, 0);
|
|
|
- dev_info(dev, "override lower: %u\n", inf->modes[0].lower_margin);
|
|
|
- } else if (!strncmp(this_opt, "hsynclen:", 9)) {
|
|
|
- inf->modes[0].hsync_len = simple_strtoul(this_opt+9, NULL, 0);
|
|
|
- dev_info(dev, "override hsynclen: %u\n", inf->modes[0].hsync_len);
|
|
|
- } else if (!strncmp(this_opt, "vsynclen:", 9)) {
|
|
|
- inf->modes[0].vsync_len = simple_strtoul(this_opt+9, NULL, 0);
|
|
|
- dev_info(dev, "override vsynclen: %u\n", inf->modes[0].vsync_len);
|
|
|
- } else if (!strncmp(this_opt, "hsync:", 6)) {
|
|
|
- if (simple_strtoul(this_opt+6, NULL, 0) == 0) {
|
|
|
- dev_info(dev, "override hsync: Active Low\n");
|
|
|
- inf->modes[0].sync &= ~FB_SYNC_HOR_HIGH_ACT;
|
|
|
- } else {
|
|
|
- dev_info(dev, "override hsync: Active High\n");
|
|
|
- inf->modes[0].sync |= FB_SYNC_HOR_HIGH_ACT;
|
|
|
- }
|
|
|
- } else if (!strncmp(this_opt, "vsync:", 6)) {
|
|
|
- if (simple_strtoul(this_opt+6, NULL, 0) == 0) {
|
|
|
- dev_info(dev, "override vsync: Active Low\n");
|
|
|
- inf->modes[0].sync &= ~FB_SYNC_VERT_HIGH_ACT;
|
|
|
- } else {
|
|
|
- dev_info(dev, "override vsync: Active High\n");
|
|
|
- inf->modes[0].sync |= FB_SYNC_VERT_HIGH_ACT;
|
|
|
- }
|
|
|
- } else if (!strncmp(this_opt, "dpc:", 4)) {
|
|
|
- if (simple_strtoul(this_opt+4, NULL, 0) == 0) {
|
|
|
- dev_info(dev, "override double pixel clock: false\n");
|
|
|
- inf->lccr3 &= ~LCCR3_DPC;
|
|
|
- } else {
|
|
|
- dev_info(dev, "override double pixel clock: true\n");
|
|
|
- inf->lccr3 |= LCCR3_DPC;
|
|
|
- }
|
|
|
- } else if (!strncmp(this_opt, "outputen:", 9)) {
|
|
|
- if (simple_strtoul(this_opt+9, NULL, 0) == 0) {
|
|
|
- dev_info(dev, "override output enable: active low\n");
|
|
|
- inf->lccr3 = (inf->lccr3 & ~LCCR3_OEP) | LCCR3_OutEnL;
|
|
|
- } else {
|
|
|
- dev_info(dev, "override output enable: active high\n");
|
|
|
- inf->lccr3 = (inf->lccr3 & ~LCCR3_OEP) | LCCR3_OutEnH;
|
|
|
- }
|
|
|
- } else if (!strncmp(this_opt, "pixclockpol:", 12)) {
|
|
|
- if (simple_strtoul(this_opt+12, NULL, 0) == 0) {
|
|
|
- dev_info(dev, "override pixel clock polarity: falling edge\n");
|
|
|
- inf->lccr3 = (inf->lccr3 & ~LCCR3_PCP) | LCCR3_PixFlEdg;
|
|
|
- } else {
|
|
|
- dev_info(dev, "override pixel clock polarity: rising edge\n");
|
|
|
- inf->lccr3 = (inf->lccr3 & ~LCCR3_PCP) | LCCR3_PixRsEdg;
|
|
|
- }
|
|
|
- } else if (!strncmp(this_opt, "color", 5)) {
|
|
|
- inf->lccr0 = (inf->lccr0 & ~LCCR0_CMS) | LCCR0_Color;
|
|
|
- } else if (!strncmp(this_opt, "mono", 4)) {
|
|
|
- inf->lccr0 = (inf->lccr0 & ~LCCR0_CMS) | LCCR0_Mono;
|
|
|
- } else if (!strncmp(this_opt, "active", 6)) {
|
|
|
- inf->lccr0 = (inf->lccr0 & ~LCCR0_PAS) | LCCR0_Act;
|
|
|
- } else if (!strncmp(this_opt, "passive", 7)) {
|
|
|
- inf->lccr0 = (inf->lccr0 & ~LCCR0_PAS) | LCCR0_Pas;
|
|
|
- } else if (!strncmp(this_opt, "single", 6)) {
|
|
|
- inf->lccr0 = (inf->lccr0 & ~LCCR0_SDS) | LCCR0_Sngl;
|
|
|
- } else if (!strncmp(this_opt, "dual", 4)) {
|
|
|
- inf->lccr0 = (inf->lccr0 & ~LCCR0_SDS) | LCCR0_Dual;
|
|
|
- } else if (!strncmp(this_opt, "4pix", 4)) {
|
|
|
- inf->lccr0 = (inf->lccr0 & ~LCCR0_DPD) | LCCR0_4PixMono;
|
|
|
- } else if (!strncmp(this_opt, "8pix", 4)) {
|
|
|
- inf->lccr0 = (inf->lccr0 & ~LCCR0_DPD) | LCCR0_8PixMono;
|
|
|
- } else {
|
|
|
- dev_err(dev, "unknown option: %s\n", this_opt);
|
|
|
- return -EINVAL;
|
|
|
- }
|
|
|
- }
|
|
|
- return 0;
|
|
|
-
|
|
|
+ while ((this_opt = strsep(&options, ",")) != NULL) {
|
|
|
+ ret = parse_opt(dev, this_opt);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
}
|
|
|
#endif
|
|
|
|