On Thu, Jun 14, 2012 at 03:43:25PM +0200, Sascha Hauer wrote:
...
> +#include <linux/device.h>
> +#include <linux/platform_device.h>
> +#include <drm/drmP.h>
> +#include <drm/drm_fb_helper.h>
> +#include <drm/drm_crtc_helper.h>
> +#include <drm/drm_gem_cma_helper.h>
> +#include <drm/drm_fb_cma_helper.h>
> +#include <linux/fb.h>
> +#include <linux/clk.h>
> +#include <linux/module.h>
> +#include <mach/hardware.h>

This looks suspicious.

> +#include <mach/imxfb.h>

We should probably copy those needed macros into the file to save this
<mach> inclusion?

> +#include <generated/mach-types.h>
> +#include <drm/drm_gem_cma_helper.h>
> +
> +#include "imx-drm.h"
> +
> +#define LCDC_SSA             0x00
> +#define LCDC_SIZE            0x04
> +#define LCDC_VPW             0x08
> +#define LCDC_CPOS            0x0C
> +#define LCDC_LCWHB           0x10
> +#define LCDC_LCHCC           0x14
> +#define LCDC_PCR             0x18
> +#define LCDC_HCR             0x1C
> +#define LCDC_VCR             0x20
> +#define LCDC_POS             0x24
> +#define LCDC_LSCR1           0x28
> +#define LCDC_PWMR            0x2C
> +#define LCDC_DMACR           0x30
> +#define LCDC_RMCR            0x34
> +#define LCDC_LCDICR          0x38
> +#define LCDC_LIER            0x3c
> +#define LCDC_LISR            0x40
> +
> +#define SIZE_XMAX(x)         ((((x) >> 4) & 0x3f) << 20)
> +
> +#define YMAX_MASK            (cpu_is_mx1() ? 0x1ff : 0x3ff)

Ah, here it needs <mach/hardware.h>.  We may not want to use
cpu_is_mx1() any more.

> +#define SIZE_YMAX(y)         ((y) & YMAX_MASK)
> +
> +#define VPW_VPW(x)           ((x) & 0x3ff)
> +
> +#define HCR_H_WIDTH(x)               (((x) & 0x3f) << 26)
> +#define HCR_H_WAIT_1(x)              (((x) & 0xff) << 8)
> +#define HCR_H_WAIT_2(x)              ((x) & 0xff)
> +
> +#define VCR_V_WIDTH(x)               (((x) & 0x3f) << 26)
> +#define VCR_V_WAIT_1(x)              (((x) & 0xff) << 8)
> +#define VCR_V_WAIT_2(x)              ((x) & 0xff)
> +
> +#define RMCR_LCDC_EN_MX1     (1 << 1)
> +
> +#define RMCR_SELF_REF                (1 << 0)
> +
> +#define LIER_EOF             (1 << 1)
> +
> +struct imx_crtc {
> +     struct drm_crtc         base;
> +     struct imx_drm_crtc     *imx_drm_crtc;
> +     int                     di_no;
> +     int                     enabled;
> +     void __iomem            *regs;
> +     u32                     pwmr;
> +     u32                     lscr1;
> +     u32                     dmacr;
> +     u32                     pcr;
> +     struct clk              *clk;
> +     struct device           *dev;
> +     int                     vblank_enable;
> +
> +     struct drm_pending_vblank_event *page_flip_event;
> +     struct drm_framebuffer  *newfb;
> +};
> +
> +#define to_imx_crtc(x) container_of(x, struct imx_crtc, base)
> +
> +static void imx_crtc_load_lut(struct drm_crtc *crtc)
> +{
> +}
> +
> +#define PCR_BPIX_8           (3 << 25)
> +#define PCR_BPIX_12          (4 << 25)
> +#define PCR_BPIX_16          (5 << 25)
> +#define PCR_BPIX_18          (6 << 25)
> +#define PCR_END_SEL          (1 << 18)
> +#define PCR_END_BYTE_SWAP    (1 << 17)
> +
> +static const char *fourcc_to_str(u32 fourcc)
> +{
> +     static char buf[5];
> +
> +     *(u32 *)buf = fourcc;
> +     buf[4] = 0;
> +
> +     return buf;
> +}
> +
> +static int imx_drm_crtc_set(struct drm_crtc *crtc,
> +             struct drm_display_mode *mode)
> +{
> +     struct imx_crtc *imx_crtc = to_imx_crtc(crtc);
> +     struct drm_framebuffer *fb = crtc->fb;
> +     int lower_margin = mode->vsync_start - mode->vdisplay;
> +     int upper_margin = mode->vtotal - mode->vsync_end;
> +     int vsync_len = mode->vsync_end - mode->vsync_start;
> +     int hsync_len = mode->hsync_end - mode->hsync_start;
> +     int right_margin = mode->hsync_start - mode->hdisplay;
> +     int left_margin = mode->htotal - mode->hsync_end;
> +     unsigned long lcd_clk;
> +     u32 pcr;
> +
> +     lcd_clk = clk_get_rate(imx_crtc->clk) / 1000;
> +
> +     if (!mode->clock)
> +             return -EINVAL;
> +
> +     pcr = DIV_ROUND_CLOSEST(lcd_clk, mode->clock);
> +     if (--pcr > 0x3f)
> +             pcr = 0x3f;
> +
> +     switch (fb->pixel_format) {
> +     case DRM_FORMAT_XRGB8888:
> +     case DRM_FORMAT_ARGB8888:
> +             pcr |= PCR_BPIX_18;
> +             pcr |= PCR_END_SEL | PCR_END_BYTE_SWAP;
> +             break;
> +     case DRM_FORMAT_RGB565:
> +             if (cpu_is_mx1())

Ditto

> +                     pcr |= PCR_BPIX_12;
> +             else
> +                     pcr |= PCR_BPIX_16;
> +             break;
> +     case DRM_FORMAT_RGB332:
> +             pcr |= PCR_BPIX_8;
> +             break;
> +     default:
> +             dev_err(imx_crtc->dev, "unsupported pixel format %s\n",
> +                             fourcc_to_str(fb->pixel_format));
> +             return -EINVAL;
> +     }
> +
> +     /* add sync polarities */
> +     pcr |= imx_crtc->pcr & ~(0x3f | (7 << 25));
> +
> +     dev_dbg(imx_crtc->dev,
> +                     "xres=%d hsync_len=%d left_margin=%d right_margin=%d\n",
> +                     mode->hdisplay, hsync_len,
> +                     left_margin, right_margin);
> +     dev_dbg(imx_crtc->dev,
> +                     "yres=%d vsync_len=%d upper_margin=%d 
> lower_margin=%d\n",
> +                     mode->vdisplay, vsync_len,
> +                     upper_margin, lower_margin);
> +
> +     writel(VPW_VPW(mode->hdisplay * fb->bits_per_pixel / 8 / 4),
> +             imx_crtc->regs + LCDC_VPW);
> +
> +     writel(HCR_H_WIDTH(hsync_len - 1) |
> +             HCR_H_WAIT_1(right_margin - 1) |
> +             HCR_H_WAIT_2(left_margin - 3),
> +             imx_crtc->regs + LCDC_HCR);
> +
> +     writel(VCR_V_WIDTH(vsync_len) |
> +             VCR_V_WAIT_1(lower_margin) |
> +             VCR_V_WAIT_2(upper_margin),
> +             imx_crtc->regs + LCDC_VCR);
> +
> +     writel(SIZE_XMAX(mode->hdisplay) | SIZE_YMAX(mode->vdisplay),
> +                     imx_crtc->regs + LCDC_SIZE);
> +
> +     writel(pcr, imx_crtc->regs + LCDC_PCR);
> +     writel(imx_crtc->pwmr, imx_crtc->regs + LCDC_PWMR);
> +     writel(imx_crtc->lscr1, imx_crtc->regs + LCDC_LSCR1);
> +     /* reset default */
> +     writel(0x00040060, imx_crtc->regs + LCDC_DMACR);
> +
> +     return 0;
> +}

...

> +static int __devinit imx_crtc_probe(struct platform_device *pdev)
> +{
> +     struct imx_crtc *imx_crtc;
> +     struct resource *res;
> +     int ret, irq;
> +     u32 pcr_value = 0xf00080c0;
> +     u32 lscr1_value = 0x00120300;
> +     u32 pwmr_value = 0x00a903ff;
> +
> +     imx_crtc = devm_kzalloc(&pdev->dev, sizeof(*imx_crtc), GFP_KERNEL);
> +     if (!imx_crtc)
> +             return -ENOMEM;
> +
> +     imx_crtc->dev = &pdev->dev;
> +
> +     res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +     if (!res)
> +             return -ENODEV;
> +
> +     res = devm_request_mem_region(&pdev->dev, res->start,
> +                     resource_size(res), DRIVER_NAME);
> +     if (!res)
> +             return -EBUSY;
> +
> +     imx_crtc->regs = devm_ioremap(&pdev->dev, res->start,
> +                     resource_size(res));
> +     if (!imx_crtc->regs) {
> +             dev_err(&pdev->dev, "Cannot map frame buffer registers\n");
> +             return -EBUSY;
> +     }

devm_request_and_ioremap() can help a little bit.

> +
> +     irq = platform_get_irq(pdev, 0);
> +     ret = devm_request_irq(&pdev->dev, irq, imx_irq_handler, 0, "imx_drm",
> +                     imx_crtc);
> +     if (ret < 0) {
> +             dev_err(&pdev->dev, "irq request failed with %d\n", ret);
> +             return ret;
> +     }
> +
> +     imx_crtc->clk = clk_get(&pdev->dev, NULL);
> +     if (IS_ERR(imx_crtc->clk)) {
> +             ret = PTR_ERR(imx_crtc->clk);
> +             dev_err(&pdev->dev, "unable to get clock: %d\n", ret);
> +             return ret;
> +     }
> +
> +     clk_prepare_enable(imx_crtc->clk);
> +     imx_crtc->enabled = 1;
> +
> +     platform_set_drvdata(pdev, imx_crtc);
> +
> +     imx_crtc->pcr = pcr_value & PDATA_PCR;
> +
> +     if (imx_crtc->pcr != pcr_value)
> +             dev_err(&pdev->dev, "invalid bits set in pcr: 0x%08x\n",
> +                             pcr_value & ~PDATA_PCR);
> +
> +     imx_crtc->lscr1 = lscr1_value;
> +     imx_crtc->pwmr = pwmr_value;
> +
> +     ret = imx_drm_add_crtc(&imx_crtc->base,
> +                     &imx_crtc->imx_drm_crtc,
> +                     &imx_imx_drm_helper, THIS_MODULE,
> +                     pdev->dev.of_node, 0);
> +     if (ret)
> +             goto err_init;
> +
> +     dev_info(&pdev->dev, "probed\n");
> +
> +     return 0;
> +
> +err_init:
> +     clk_disable_unprepare(imx_crtc->clk);
> +     clk_put(imx_crtc->clk);
> +
> +     return ret;
> +}
> +
> +static int __devexit imx_crtc_remove(struct platform_device *pdev)
> +{
> +     struct imx_crtc *imx_crtc = platform_get_drvdata(pdev);
> +
> +     imx_drm_remove_crtc(imx_crtc->imx_drm_crtc);
> +
> +     writel(0, imx_crtc->regs + LCDC_LIER);
> +
> +     clk_disable_unprepare(imx_crtc->clk);
> +     clk_put(imx_crtc->clk);
> +
> +     platform_set_drvdata(pdev, NULL);
> +
> +     return 0;
> +}
> +
> +static const struct of_device_id imx_lcdc_dt_ids[] = {
> +     { .compatible = "fsl,imx1-lcdc", .data = NULL, },
> +     { .compatible = "fsl,imx21-lcdc", .data = NULL, },

So .data will be used to kill those cpu_is_xxx uses.

> +     { /* sentinel */ }
> +};
> +
> +static struct platform_driver imx_crtc_driver = {
> +     .remove         = __devexit_p(imx_crtc_remove),
> +     .probe          = imx_crtc_probe,
> +     .driver         = {
> +             .name   = DRIVER_NAME,
> +             .owner  = THIS_MODULE,
> +             .of_match_table = imx_lcdc_dt_ids,
> +     },
> +};
> +
> +static int __init imx_lcdc_init(void)
> +{
> +     return platform_driver_register(&imx_crtc_driver);
> +}
> +
> +static void __exit imx_lcdc_exit(void)
> +{
> +     platform_driver_unregister(&imx_crtc_driver);
> +}
> +
> +module_init(imx_lcdc_init);
> +module_exit(imx_lcdc_exit)

Can these simply be module_platform_driver(imx_crtc_driver)?

> +
> +MODULE_DESCRIPTION("Freescale i.MX framebuffer driver");
> +MODULE_AUTHOR("Sascha Hauer, Pengutronix");
> +MODULE_LICENSE("GPL");
> -- 
> 1.7.10
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-ker...@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

-- 
Regards,
Shawn

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to