OMAPDSS: Merge omapdss topic branches
Tomi Valkeinen [Mon, 15 Apr 2013 08:57:18 +0000 (11:57 +0300)]
1  2  3 
drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c
drivers/video/omap2/displays/panel-taal.c
drivers/video/omap2/dss/dispc.c
drivers/video/omap2/dss/dsi.c
drivers/video/omap2/dss/dss.c
drivers/video/omap2/dss/hdmi.c
drivers/video/omap2/dss/venc.c

@@@@ -81,35 -84,72 -84,72 +81,35 @@@@ static struct omap_video_timings nec_80
        .sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
   };
   
 --static int nec_8048_bl_update_status(struct backlight_device *bl)
 --{
 --     struct omap_dss_device *dssdev = dev_get_drvdata(&bl->dev);
 --     int level;
 --
 --     if (!dssdev->set_backlight)
 --             return -EINVAL;
 --
 --     if (bl->props.fb_blank == FB_BLANK_UNBLANK &&
 --                     bl->props.power == FB_BLANK_UNBLANK)
 --             level = bl->props.brightness;
 --     else
 --             level = 0;
 --
 --     return dssdev->set_backlight(dssdev, level);
 --}
 --
 --static int nec_8048_bl_get_brightness(struct backlight_device *bl)
 ++static inline struct panel_nec_nl8048_data
 ++*get_panel_data(const struct omap_dss_device *dssdev)
   {
 --     if (bl->props.fb_blank == FB_BLANK_UNBLANK &&
 --                     bl->props.power == FB_BLANK_UNBLANK)
 --             return bl->props.brightness;
 --
 --     return 0;
 ++     return (struct panel_nec_nl8048_data *) dssdev->data;
   }
   
 --static const struct backlight_ops nec_8048_bl_ops = {
 --     .get_brightness = nec_8048_bl_get_brightness,
 --     .update_status  = nec_8048_bl_update_status,
 --};
 --
   static int nec_8048_panel_probe(struct omap_dss_device *dssdev)
   {
 --     struct backlight_device *bl;
 --     struct nec_8048_data *necd;
 --     struct backlight_properties props;
 ++     struct panel_nec_nl8048_data *pd = get_panel_data(dssdev);
        int r;
   
 --     dssdev->panel.timings = nec_8048_panel_timings;
 --
 --     necd = kzalloc(sizeof(*necd), GFP_KERNEL);
 --     if (!necd)
 --             return -ENOMEM;
 --
 --     dev_set_drvdata(&dssdev->dev, necd);
 ++     if (!pd)
 ++             return -EINVAL;
   
 --     memset(&props, 0, sizeof(struct backlight_properties));
 --     props.max_brightness = 255;
 ++     dssdev->panel.timings = nec_8048_panel_timings;
   
 --     bl = backlight_device_register("nec-8048", &dssdev->dev, dssdev,
 --                     &nec_8048_bl_ops, &props);
 --     if (IS_ERR(bl)) {
 --             r = PTR_ERR(bl);
 --             kfree(necd);
 --             return r;
 ++     if (gpio_is_valid(pd->qvga_gpio)) {
 ++             r = devm_gpio_request_one(&dssdev->dev, pd->qvga_gpio,
 ++                             GPIOF_OUT_INIT_HIGH, "lcd QVGA");
 ++             if (r)
 ++                     return r;
        }
 --     necd->bl = bl;
 - 
 -      bl->props.fb_blank = FB_BLANK_UNBLANK;
 -      bl->props.power = FB_BLANK_UNBLANK;
 -      bl->props.max_brightness = dssdev->max_backlight_level;
 -      bl->props.brightness = dssdev->max_backlight_level;
   
 -      r = nec_8048_bl_update_status(bl);
 -      if (r < 0)
 -              dev_err(&dssdev->dev, "failed to set lcd brightness\n");
  -     bl->props.fb_blank = FB_BLANK_UNBLANK;
  -     bl->props.power = FB_BLANK_UNBLANK;
  -     bl->props.max_brightness = dssdev->max_backlight_level;
  -     bl->props.brightness = dssdev->max_backlight_level;
  -
  -     r = nec_8048_bl_update_status(bl);
  -     if (r < 0)
  -             dev_err(&dssdev->dev, "failed to set lcd brightness\n");
 ++     if (gpio_is_valid(pd->res_gpio)) {
 ++             r = devm_gpio_request_one(&dssdev->dev, pd->res_gpio,
 ++                             GPIOF_OUT_INIT_LOW, "lcd RES");
 ++             if (r)
 ++                     return r;
 ++     }
   
        return 0;
   }
Simple merge
@@@@ -4881,64 -4653,481 -4881,64 +4653,481 @@@@ int omapdss_dsi_enable_te(struct omap_d
   }
   EXPORT_SYMBOL(omapdss_dsi_enable_te);
   
- -void omapdss_dsi_set_timings(struct omap_dss_device *dssdev,
- -             struct omap_video_timings *timings)
+ +#ifdef PRINT_VERBOSE_VM_TIMINGS
+ +static void print_dsi_vm(const char *str,
+ +             const struct omap_dss_dsi_videomode_timings *t)
+ +{
+ +     unsigned long byteclk = t->hsclk / 4;
+ +     int bl, wc, pps, tot;
+ +
+ +     wc = DIV_ROUND_UP(t->hact * t->bitspp, 8);
+ +     pps = DIV_ROUND_UP(wc + 6, t->ndl); /* pixel packet size */
+ +     bl = t->hss + t->hsa + t->hse + t->hbp + t->hfp;
+ +     tot = bl + pps;
+ +
+ +#define TO_DSI_T(x) ((u32)div64_u64((u64)x * 1000000000llu, byteclk))
+ +
+ +     pr_debug("%s bck %lu, %u/%u/%u/%u/%u/%u = %u+%u = %u, "
+ +                     "%u/%u/%u/%u/%u/%u = %u + %u = %u\n",
+ +                     str,
+ +                     byteclk,
+ +                     t->hss, t->hsa, t->hse, t->hbp, pps, t->hfp,
+ +                     bl, pps, tot,
+ +                     TO_DSI_T(t->hss),
+ +                     TO_DSI_T(t->hsa),
+ +                     TO_DSI_T(t->hse),
+ +                     TO_DSI_T(t->hbp),
+ +                     TO_DSI_T(pps),
+ +                     TO_DSI_T(t->hfp),
+ +
+ +                     TO_DSI_T(bl),
+ +                     TO_DSI_T(pps),
+ +
+ +                     TO_DSI_T(tot));
+ +#undef TO_DSI_T
+ +}
+ +
+ +static void print_dispc_vm(const char *str, const struct omap_video_timings *t)
+ +{
+ +     unsigned long pck = t->pixel_clock * 1000;
+ +     int hact, bl, tot;
+ +
+ +     hact = t->x_res;
+ +     bl = t->hsw + t->hbp + t->hfp;
+ +     tot = hact + bl;
+ +
+ +#define TO_DISPC_T(x) ((u32)div64_u64((u64)x * 1000000000llu, pck))
+ +
+ +     pr_debug("%s pck %lu, %u/%u/%u/%u = %u+%u = %u, "
+ +                     "%u/%u/%u/%u = %u + %u = %u\n",
+ +                     str,
+ +                     pck,
+ +                     t->hsw, t->hbp, hact, t->hfp,
+ +                     bl, hact, tot,
+ +                     TO_DISPC_T(t->hsw),
+ +                     TO_DISPC_T(t->hbp),
+ +                     TO_DISPC_T(hact),
+ +                     TO_DISPC_T(t->hfp),
+ +                     TO_DISPC_T(bl),
+ +                     TO_DISPC_T(hact),
+ +                     TO_DISPC_T(tot));
+ +#undef TO_DISPC_T
+ +}
+ +
+ +/* note: this is not quite accurate */
+ +static void print_dsi_dispc_vm(const char *str,
+ +             const struct omap_dss_dsi_videomode_timings *t)
+ +{
+ +     struct omap_video_timings vm = { 0 };
+ +     unsigned long byteclk = t->hsclk / 4;
+ +     unsigned long pck;
+ +     u64 dsi_tput;
+ +     int dsi_hact, dsi_htot;
+ +
+ +     dsi_tput = (u64)byteclk * t->ndl * 8;
+ +     pck = (u32)div64_u64(dsi_tput, t->bitspp);
+ +     dsi_hact = DIV_ROUND_UP(DIV_ROUND_UP(t->hact * t->bitspp, 8) + 6, t->ndl);
+ +     dsi_htot = t->hss + t->hsa + t->hse + t->hbp + dsi_hact + t->hfp;
+ +
+ +     vm.pixel_clock = pck / 1000;
+ +     vm.hsw = div64_u64((u64)(t->hsa + t->hse) * pck, byteclk);
+ +     vm.hbp = div64_u64((u64)t->hbp * pck, byteclk);
+ +     vm.hfp = div64_u64((u64)t->hfp * pck, byteclk);
+ +     vm.x_res = t->hact;
+ +
+ +     print_dispc_vm(str, &vm);
+ +}
+ +#endif /* PRINT_VERBOSE_VM_TIMINGS */
+ +
+ +static bool dsi_cm_calc_dispc_cb(int lckd, int pckd, unsigned long lck,
+ +             unsigned long pck, void *data)
   {
- -     struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
- -     struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+ +     struct dsi_clk_calc_ctx *ctx = data;
+ +     struct omap_video_timings *t = &ctx->dispc_vm;
   
- -     mutex_lock(&dsi->lock);
+ +     ctx->dispc_cinfo.lck_div = lckd;
+ +     ctx->dispc_cinfo.pck_div = pckd;
+ +     ctx->dispc_cinfo.lck = lck;
+ +     ctx->dispc_cinfo.pck = pck;
   
- -     dsi->timings = *timings;
+ +     *t = *ctx->config->timings;
+ +     t->pixel_clock = pck / 1000;
+ +     t->x_res = ctx->config->timings->x_res;
+ +     t->y_res = ctx->config->timings->y_res;
+ +     t->hsw = t->hfp = t->hbp = t->vsw = 1;
+ +     t->vfp = t->vbp = 0;
   
- -     mutex_unlock(&dsi->lock);
+ +     return true;
   }
- -EXPORT_SYMBOL(omapdss_dsi_set_timings);
   
- -void omapdss_dsi_set_size(struct omap_dss_device *dssdev, u16 w, u16 h)
+ +static bool dsi_cm_calc_hsdiv_cb(int regm_dispc, unsigned long dispc,
+ +             void *data)
   {
- -     struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
- -     struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+ +     struct dsi_clk_calc_ctx *ctx = data;
   
- -     mutex_lock(&dsi->lock);
+ +     ctx->dsi_cinfo.regm_dispc = regm_dispc;
+ +     ctx->dsi_cinfo.dsi_pll_hsdiv_dispc_clk = dispc;
   
- -     dsi->timings.x_res = w;
- -     dsi->timings.y_res = h;
+ +     return dispc_div_calc(dispc, ctx->req_pck_min, ctx->req_pck_max,
+ +                     dsi_cm_calc_dispc_cb, ctx);
+ +}
   
- -     mutex_unlock(&dsi->lock);
+ +static bool dsi_cm_calc_pll_cb(int regn, int regm, unsigned long fint,
+ +             unsigned long pll, void *data)
+ +{
+ +     struct dsi_clk_calc_ctx *ctx = data;
+ +
+ +     ctx->dsi_cinfo.regn = regn;
+ +     ctx->dsi_cinfo.regm = regm;
+ +     ctx->dsi_cinfo.fint = fint;
+ +     ctx->dsi_cinfo.clkin4ddr = pll;
+ +
+ +     return dsi_hsdiv_calc(ctx->dsidev, pll, ctx->req_pck_min,
+ +                     dsi_cm_calc_hsdiv_cb, ctx);
   }
- -EXPORT_SYMBOL(omapdss_dsi_set_size);
   
- -void omapdss_dsi_set_pixel_format(struct omap_dss_device *dssdev,
- -             enum omap_dss_dsi_pixel_format fmt)
+ +static bool dsi_cm_calc(struct dsi_data *dsi,
+ +             const struct omap_dss_dsi_config *cfg,
+ +             struct dsi_clk_calc_ctx *ctx)
   {
- -     struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
- -     struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+ +     unsigned long clkin;
+ +     int bitspp, ndl;
+ +     unsigned long pll_min, pll_max;
+ +     unsigned long pck, txbyteclk;
   
- -     mutex_lock(&dsi->lock);
+ +     clkin = clk_get_rate(dsi->sys_clk);
+ +     bitspp = dsi_get_pixel_size(cfg->pixel_format);
+ +     ndl = dsi->num_lanes_used - 1;
+  
  -     dsi->pix_fmt = fmt;
+ +     /*
+ +      * Here we should calculate minimum txbyteclk to be able to send the
+ +      * frame in time, and also to handle TE. That's not very simple, though,
+ +      * especially as we go to LP between each pixel packet due to HW
+ +      * "feature". So let's just estimate very roughly and multiply by 1.5.
+ +      */
+ +     pck = cfg->timings->pixel_clock * 1000;
+ +     pck = pck * 3 / 2;
+ +     txbyteclk = pck * bitspp / 8 / ndl;
   
-       dsi->pix_fmt = fmt;
  -     mutex_unlock(&dsi->lock);
+ +     memset(ctx, 0, sizeof(*ctx));
+ +     ctx->dsidev = dsi->pdev;
+ +     ctx->config = cfg;
+ +     ctx->req_pck_min = pck;
+ +     ctx->req_pck_nom = pck;
+ +     ctx->req_pck_max = pck * 3 / 2;
+ +     ctx->dsi_cinfo.clkin = clkin;
  +
-       mutex_unlock(&dsi->lock);
+ +     pll_min = max(cfg->hs_clk_min * 4, txbyteclk * 4 * 4);
+ +     pll_max = cfg->hs_clk_max * 4;
+ +
+ +     return dsi_pll_calc(dsi->pdev, clkin,
+ +                     pll_min, pll_max,
+ +                     dsi_cm_calc_pll_cb, ctx);
   }
- -EXPORT_SYMBOL(omapdss_dsi_set_pixel_format);
   
- -void omapdss_dsi_set_operation_mode(struct omap_dss_device *dssdev,
- -             enum omap_dss_dsi_mode mode)
+ +static bool dsi_vm_calc_blanking(struct dsi_clk_calc_ctx *ctx)
   {
- -     struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
- -     struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
+ +     struct dsi_data *dsi = dsi_get_dsidrv_data(ctx->dsidev);
+ +     const struct omap_dss_dsi_config *cfg = ctx->config;
+ +     int bitspp = dsi_get_pixel_size(cfg->pixel_format);
+ +     int ndl = dsi->num_lanes_used - 1;
+ +     unsigned long hsclk = ctx->dsi_cinfo.clkin4ddr / 4;
+ +     unsigned long byteclk = hsclk / 4;
   
- -     mutex_lock(&dsi->lock);
+ +     unsigned long dispc_pck, req_pck_min, req_pck_nom, req_pck_max;
+ +     int xres;
+ +     int panel_htot, panel_hbl; /* pixels */
+ +     int dispc_htot, dispc_hbl; /* pixels */
+ +     int dsi_htot, dsi_hact, dsi_hbl, hss, hse; /* byteclks */
+ +     int hfp, hsa, hbp;
+ +     const struct omap_video_timings *req_vm;
+ +     struct omap_video_timings *dispc_vm;
+ +     struct omap_dss_dsi_videomode_timings *dsi_vm;
+ +     u64 dsi_tput, dispc_tput;
   
- -     dsi->mode = mode;
+ +     dsi_tput = (u64)byteclk * ndl * 8;
   
- -     mutex_unlock(&dsi->lock);
+ +     req_vm = cfg->timings;
+ +     req_pck_min = ctx->req_pck_min;
+ +     req_pck_max = ctx->req_pck_max;
+ +     req_pck_nom = ctx->req_pck_nom;
+ +
+ +     dispc_pck = ctx->dispc_cinfo.pck;
+ +     dispc_tput = (u64)dispc_pck * bitspp;
+ +
+ +     xres = req_vm->x_res;
+ +
+ +     panel_hbl = req_vm->hfp + req_vm->hbp + req_vm->hsw;
+ +     panel_htot = xres + panel_hbl;
+ +
+ +     dsi_hact = DIV_ROUND_UP(DIV_ROUND_UP(xres * bitspp, 8) + 6, ndl);
+ +
+ +     /*
+ +      * When there are no line buffers, DISPC and DSI must have the
+ +      * same tput. Otherwise DISPC tput needs to be higher than DSI's.
+ +      */
+ +     if (dsi->line_buffer_size < xres * bitspp / 8) {
+ +             if (dispc_tput != dsi_tput)
+ +                     return false;
+ +     } else {
+ +             if (dispc_tput < dsi_tput)
+ +                     return false;
+ +     }
+ +
+ +     /* DSI tput must be over the min requirement */
+ +     if (dsi_tput < (u64)bitspp * req_pck_min)
+ +             return false;
+ +
+ +     /* When non-burst mode, DSI tput must be below max requirement. */
+ +     if (cfg->trans_mode != OMAP_DSS_DSI_BURST_MODE) {
+ +             if (dsi_tput > (u64)bitspp * req_pck_max)
+ +                     return false;
+ +     }
+ +
+ +     hss = DIV_ROUND_UP(4, ndl);
+ +
+ +     if (cfg->trans_mode == OMAP_DSS_DSI_PULSE_MODE) {
+ +             if (ndl == 3 && req_vm->hsw == 0)
+ +                     hse = 1;
+ +             else
+ +                     hse = DIV_ROUND_UP(4, ndl);
+ +     } else {
+ +             hse = 0;
+ +     }
+ +
+ +     /* DSI htot to match the panel's nominal pck */
+ +     dsi_htot = div64_u64((u64)panel_htot * byteclk, req_pck_nom);
+ +
+ +     /* fail if there would be no time for blanking */
+ +     if (dsi_htot < hss + hse + dsi_hact)
+ +             return false;
+ +
+ +     /* total DSI blanking needed to achieve panel's TL */
+ +     dsi_hbl = dsi_htot - dsi_hact;
+ +
+ +     /* DISPC htot to match the DSI TL */
+ +     dispc_htot = div64_u64((u64)dsi_htot * dispc_pck, byteclk);
+ +
+ +     /* verify that the DSI and DISPC TLs are the same */
+ +     if ((u64)dsi_htot * dispc_pck != (u64)dispc_htot * byteclk)
+ +             return false;
+ +
+ +     dispc_hbl = dispc_htot - xres;
+ +
+ +     /* setup DSI videomode */
+ +
+ +     dsi_vm = &ctx->dsi_vm;
+ +     memset(dsi_vm, 0, sizeof(*dsi_vm));
+ +
+ +     dsi_vm->hsclk = hsclk;
+ +
+ +     dsi_vm->ndl = ndl;
+ +     dsi_vm->bitspp = bitspp;
+ +
+ +     if (cfg->trans_mode != OMAP_DSS_DSI_PULSE_MODE) {
+ +             hsa = 0;
+ +     } else if (ndl == 3 && req_vm->hsw == 0) {
+ +             hsa = 0;
+ +     } else {
+ +             hsa = div64_u64((u64)req_vm->hsw * byteclk, req_pck_nom);
+ +             hsa = max(hsa - hse, 1);
+ +     }
+ +
+ +     hbp = div64_u64((u64)req_vm->hbp * byteclk, req_pck_nom);
+ +     hbp = max(hbp, 1);
+ +
+ +     hfp = dsi_hbl - (hss + hsa + hse + hbp);
+ +     if (hfp < 1) {
+ +             int t;
+ +             /* we need to take cycles from hbp */
+ +
+ +             t = 1 - hfp;
+ +             hbp = max(hbp - t, 1);
+ +             hfp = dsi_hbl - (hss + hsa + hse + hbp);
+ +
+ +             if (hfp < 1 && hsa > 0) {
+ +                     /* we need to take cycles from hsa */
+ +                     t = 1 - hfp;
+ +                     hsa = max(hsa - t, 1);
+ +                     hfp = dsi_hbl - (hss + hsa + hse + hbp);
+ +             }
+ +     }
+ +
+ +     if (hfp < 1)
+ +             return false;
+ +
+ +     dsi_vm->hss = hss;
+ +     dsi_vm->hsa = hsa;
+ +     dsi_vm->hse = hse;
+ +     dsi_vm->hbp = hbp;
+ +     dsi_vm->hact = xres;
+ +     dsi_vm->hfp = hfp;
+ +
+ +     dsi_vm->vsa = req_vm->vsw;
+ +     dsi_vm->vbp = req_vm->vbp;
+ +     dsi_vm->vact = req_vm->y_res;
+ +     dsi_vm->vfp = req_vm->vfp;
+ +
+ +     dsi_vm->trans_mode = cfg->trans_mode;
+ +
+ +     dsi_vm->blanking_mode = 0;
+ +     dsi_vm->hsa_blanking_mode = 1;
+ +     dsi_vm->hfp_blanking_mode = 1;
+ +     dsi_vm->hbp_blanking_mode = 1;
+ +
+ +     dsi_vm->ddr_clk_always_on = cfg->ddr_clk_always_on;
+ +     dsi_vm->window_sync = 4;
+ +
+ +     /* setup DISPC videomode */
+ +
+ +     dispc_vm = &ctx->dispc_vm;
+ +     *dispc_vm = *req_vm;
+ +     dispc_vm->pixel_clock = dispc_pck / 1000;
+ +
+ +     if (cfg->trans_mode == OMAP_DSS_DSI_PULSE_MODE) {
+ +             hsa = div64_u64((u64)req_vm->hsw * dispc_pck,
+ +                             req_pck_nom);
+ +             hsa = max(hsa, 1);
+ +     } else {
+ +             hsa = 1;
+ +     }
+ +
+ +     hbp = div64_u64((u64)req_vm->hbp * dispc_pck, req_pck_nom);
+ +     hbp = max(hbp, 1);
+ +
+ +     hfp = dispc_hbl - hsa - hbp;
+ +     if (hfp < 1) {
+ +             int t;
+ +             /* we need to take cycles from hbp */
+ +
+ +             t = 1 - hfp;
+ +             hbp = max(hbp - t, 1);
+ +             hfp = dispc_hbl - hsa - hbp;
+ +
+ +             if (hfp < 1) {
+ +                     /* we need to take cycles from hsa */
+ +                     t = 1 - hfp;
+ +                     hsa = max(hsa - t, 1);
+ +                     hfp = dispc_hbl - hsa - hbp;
+ +             }
+ +     }
+ +
+ +     if (hfp < 1)
+ +             return false;
+ +
+ +     dispc_vm->hfp = hfp;
+ +     dispc_vm->hsw = hsa;
+ +     dispc_vm->hbp = hbp;
+ +
+ +     return true;
+ +}
+ +
+ +
+ +static bool dsi_vm_calc_dispc_cb(int lckd, int pckd, unsigned long lck,
+ +             unsigned long pck, void *data)
+ +{
+ +     struct dsi_clk_calc_ctx *ctx = data;
+ +
+ +     ctx->dispc_cinfo.lck_div = lckd;
+ +     ctx->dispc_cinfo.pck_div = pckd;
+ +     ctx->dispc_cinfo.lck = lck;
+ +     ctx->dispc_cinfo.pck = pck;
+ +
+ +     if (dsi_vm_calc_blanking(ctx) == false)
+ +             return false;
+ +
+ +#ifdef PRINT_VERBOSE_VM_TIMINGS
+ +     print_dispc_vm("dispc", &ctx->dispc_vm);
+ +     print_dsi_vm("dsi  ", &ctx->dsi_vm);
+ +     print_dispc_vm("req  ", ctx->config->timings);
+ +     print_dsi_dispc_vm("act  ", &ctx->dsi_vm);
+ +#endif
+ +
+ +     return true;
+ +}
+ +
+ +static bool dsi_vm_calc_hsdiv_cb(int regm_dispc, unsigned long dispc,
+ +             void *data)
+ +{
+ +     struct dsi_clk_calc_ctx *ctx = data;
+ +     unsigned long pck_max;
+ +
+ +     ctx->dsi_cinfo.regm_dispc = regm_dispc;
+ +     ctx->dsi_cinfo.dsi_pll_hsdiv_dispc_clk = dispc;
+ +
+ +     /*
+ +      * In burst mode we can let the dispc pck be arbitrarily high, but it
+ +      * limits our scaling abilities. So for now, don't aim too high.
+ +      */
+ +
+ +     if (ctx->config->trans_mode == OMAP_DSS_DSI_BURST_MODE)
+ +             pck_max = ctx->req_pck_max + 10000000;
+ +     else
+ +             pck_max = ctx->req_pck_max;
+ +
+ +     return dispc_div_calc(dispc, ctx->req_pck_min, pck_max,
+ +                     dsi_vm_calc_dispc_cb, ctx);
+ +}
+ +
+ +static bool dsi_vm_calc_pll_cb(int regn, int regm, unsigned long fint,
+ +             unsigned long pll, void *data)
+ +{
+ +     struct dsi_clk_calc_ctx *ctx = data;
+ +
+ +     ctx->dsi_cinfo.regn = regn;
+ +     ctx->dsi_cinfo.regm = regm;
+ +     ctx->dsi_cinfo.fint = fint;
+ +     ctx->dsi_cinfo.clkin4ddr = pll;
+ +
+ +     return dsi_hsdiv_calc(ctx->dsidev, pll, ctx->req_pck_min,
+ +                     dsi_vm_calc_hsdiv_cb, ctx);
+  }
  -EXPORT_SYMBOL(omapdss_dsi_set_operation_mode);
+  
  -void omapdss_dsi_set_videomode_timings(struct omap_dss_device *dssdev,
  -             struct omap_dss_dsi_videomode_timings *timings)
+ +static bool dsi_vm_calc(struct dsi_data *dsi,
+ +             const struct omap_dss_dsi_config *cfg,
+ +             struct dsi_clk_calc_ctx *ctx)
+ +{
+ +     const struct omap_video_timings *t = cfg->timings;
+ +     unsigned long clkin;
+ +     unsigned long pll_min;
+ +     unsigned long pll_max;
+ +     int ndl = dsi->num_lanes_used - 1;
+ +     int bitspp = dsi_get_pixel_size(cfg->pixel_format);
+ +     unsigned long byteclk_min;
+ +
+ +     clkin = clk_get_rate(dsi->sys_clk);
+ +
+ +     memset(ctx, 0, sizeof(*ctx));
+ +     ctx->dsidev = dsi->pdev;
+ +     ctx->config = cfg;
+ +
+ +     ctx->dsi_cinfo.clkin = clkin;
+ +
+ +     /* these limits should come from the panel driver */
+ +     ctx->req_pck_min = t->pixel_clock * 1000 - 1000;
+ +     ctx->req_pck_nom = t->pixel_clock * 1000;
+ +     ctx->req_pck_max = t->pixel_clock * 1000 + 1000;
+ +
+ +     byteclk_min = div64_u64((u64)ctx->req_pck_min * bitspp, ndl * 8);
+ +     pll_min = max(cfg->hs_clk_min * 4, byteclk_min * 4 * 4);
+ +
+ +     if (cfg->trans_mode == OMAP_DSS_DSI_BURST_MODE) {
+ +             pll_max = cfg->hs_clk_max * 4;
+ +     } else {
+ +             unsigned long byteclk_max;
+ +             byteclk_max = div64_u64((u64)ctx->req_pck_max * bitspp,
+ +                             ndl * 8);
+ +
+ +             pll_max = byteclk_max * 4 * 4;
+ +     }
+ +
+ +     return dsi_pll_calc(dsi->pdev, clkin,
+ +                     pll_min, pll_max,
+ +                     dsi_vm_calc_pll_cb, ctx);
  +}
-  EXPORT_SYMBOL(omapdss_dsi_set_operation_mode);
  +
-  void omapdss_dsi_set_videomode_timings(struct omap_dss_device *dssdev,
-               struct omap_dss_dsi_videomode_timings *timings)
+ +int omapdss_dsi_set_config(struct omap_dss_device *dssdev,
+ +             const struct omap_dss_dsi_config *config)
   {
        struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev);
        struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev);
Simple merge
Simple merge
Simple merge