linux/drivers/video/sh_mipi_dsi.c
<<
>>
Prefs
   1/*
   2 * Renesas SH-mobile MIPI DSI support
   3 *
   4 * Copyright (C) 2010 Guennadi Liakhovetski <g.liakhovetski@gmx.de>
   5 *
   6 * This is free software; you can redistribute it and/or modify
   7 * it under the terms of version 2 of the GNU General Public License as
   8 * published by the Free Software Foundation.
   9 */
  10
  11#include <linux/bitmap.h>
  12#include <linux/clk.h>
  13#include <linux/delay.h>
  14#include <linux/init.h>
  15#include <linux/io.h>
  16#include <linux/platform_device.h>
  17#include <linux/pm_runtime.h>
  18#include <linux/slab.h>
  19#include <linux/string.h>
  20#include <linux/types.h>
  21#include <linux/module.h>
  22
  23#include <video/mipi_display.h>
  24#include <video/sh_mipi_dsi.h>
  25#include <video/sh_mobile_lcdc.h>
  26
  27#include "sh_mobile_lcdcfb.h"
  28
  29#define SYSCTRL         0x0000
  30#define SYSCONF         0x0004
  31#define TIMSET          0x0008
  32#define RESREQSET0      0x0018
  33#define RESREQSET1      0x001c
  34#define HSTTOVSET       0x0020
  35#define LPRTOVSET       0x0024
  36#define TATOVSET        0x0028
  37#define PRTOVSET        0x002c
  38#define DSICTRL         0x0030
  39#define DSIINTE         0x0060
  40#define PHYCTRL         0x0070
  41
  42/* relative to linkbase */
  43#define DTCTR           0x0000
  44#define VMCTR1          0x0020
  45#define VMCTR2          0x0024
  46#define VMLEN1          0x0028
  47#define VMLEN2          0x002c
  48#define CMTSRTREQ       0x0070
  49#define CMTSRTCTR       0x00d0
  50
  51/* E.g., sh7372 has 2 MIPI-DSIs - one for each LCDC */
  52#define MAX_SH_MIPI_DSI 2
  53
  54struct sh_mipi {
  55        struct sh_mobile_lcdc_entity entity;
  56
  57        void __iomem    *base;
  58        void __iomem    *linkbase;
  59        struct clk      *dsit_clk;
  60        struct platform_device *pdev;
  61};
  62
  63#define to_sh_mipi(e)   container_of(e, struct sh_mipi, entity)
  64
  65static struct sh_mipi *mipi_dsi[MAX_SH_MIPI_DSI];
  66
  67/* Protect the above array */
  68static DEFINE_MUTEX(array_lock);
  69
  70static struct sh_mipi *sh_mipi_by_handle(int handle)
  71{
  72        if (handle >= ARRAY_SIZE(mipi_dsi) || handle < 0)
  73                return NULL;
  74
  75        return mipi_dsi[handle];
  76}
  77
  78static int sh_mipi_send_short(struct sh_mipi *mipi, u8 dsi_cmd,
  79                              u8 cmd, u8 param)
  80{
  81        u32 data = (dsi_cmd << 24) | (cmd << 16) | (param << 8);
  82        int cnt = 100;
  83
  84        /* transmit a short packet to LCD panel */
  85        iowrite32(1 | data, mipi->linkbase + CMTSRTCTR);
  86        iowrite32(1, mipi->linkbase + CMTSRTREQ);
  87
  88        while ((ioread32(mipi->linkbase + CMTSRTREQ) & 1) && --cnt)
  89                udelay(1);
  90
  91        return cnt ? 0 : -ETIMEDOUT;
  92}
  93
  94#define LCD_CHAN2MIPI(c) ((c) < LCDC_CHAN_MAINLCD || (c) > LCDC_CHAN_SUBLCD ? \
  95                                -EINVAL : (c) - 1)
  96
  97static int sh_mipi_dcs(int handle, u8 cmd)
  98{
  99        struct sh_mipi *mipi = sh_mipi_by_handle(LCD_CHAN2MIPI(handle));
 100        if (!mipi)
 101                return -ENODEV;
 102        return sh_mipi_send_short(mipi, MIPI_DSI_DCS_SHORT_WRITE, cmd, 0);
 103}
 104
 105static int sh_mipi_dcs_param(int handle, u8 cmd, u8 param)
 106{
 107        struct sh_mipi *mipi = sh_mipi_by_handle(LCD_CHAN2MIPI(handle));
 108        if (!mipi)
 109                return -ENODEV;
 110        return sh_mipi_send_short(mipi, MIPI_DSI_DCS_SHORT_WRITE_PARAM, cmd,
 111                                  param);
 112}
 113
 114static void sh_mipi_dsi_enable(struct sh_mipi *mipi, bool enable)
 115{
 116        /*
 117         * enable LCDC data tx, transition to LPS after completion of each HS
 118         * packet
 119         */
 120        iowrite32(0x00000002 | enable, mipi->linkbase + DTCTR);
 121}
 122
 123static void sh_mipi_shutdown(struct platform_device *pdev)
 124{
 125        struct sh_mipi *mipi = to_sh_mipi(platform_get_drvdata(pdev));
 126
 127        sh_mipi_dsi_enable(mipi, false);
 128}
 129
 130static int sh_mipi_setup(struct sh_mipi *mipi, struct sh_mipi_dsi_info *pdata)
 131{
 132        void __iomem *base = mipi->base;
 133        struct sh_mobile_lcdc_chan_cfg *ch = pdata->lcd_chan;
 134        u32 pctype, datatype, pixfmt, linelength, vmctr2;
 135        u32 tmp, top, bottom, delay, div;
 136        bool yuv;
 137        int bpp;
 138
 139        /*
 140         * Select data format. MIPI DSI is not hot-pluggable, so, we just use
 141         * the default videomode. If this ever becomes a problem, We'll have to
 142         * move this to mipi_display_on() above and use info->var.xres
 143         */
 144        switch (pdata->data_format) {
 145        case MIPI_RGB888:
 146                pctype = 0;
 147                datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24;
 148                pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
 149                linelength = ch->lcd_modes[0].xres * 3;
 150                yuv = false;
 151                break;
 152        case MIPI_RGB565:
 153                pctype = 1;
 154                datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16;
 155                pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
 156                linelength = ch->lcd_modes[0].xres * 2;
 157                yuv = false;
 158                break;
 159        case MIPI_RGB666_LP:
 160                pctype = 2;
 161                datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18;
 162                pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
 163                linelength = ch->lcd_modes[0].xres * 3;
 164                yuv = false;
 165                break;
 166        case MIPI_RGB666:
 167                pctype = 3;
 168                datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18;
 169                pixfmt = MIPI_DCS_PIXEL_FMT_18BIT;
 170                linelength = (ch->lcd_modes[0].xres * 18 + 7) / 8;
 171                yuv = false;
 172                break;
 173        case MIPI_BGR888:
 174                pctype = 8;
 175                datatype = MIPI_DSI_PACKED_PIXEL_STREAM_24;
 176                pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
 177                linelength = ch->lcd_modes[0].xres * 3;
 178                yuv = false;
 179                break;
 180        case MIPI_BGR565:
 181                pctype = 9;
 182                datatype = MIPI_DSI_PACKED_PIXEL_STREAM_16;
 183                pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
 184                linelength = ch->lcd_modes[0].xres * 2;
 185                yuv = false;
 186                break;
 187        case MIPI_BGR666_LP:
 188                pctype = 0xa;
 189                datatype = MIPI_DSI_PIXEL_STREAM_3BYTE_18;
 190                pixfmt = MIPI_DCS_PIXEL_FMT_24BIT;
 191                linelength = ch->lcd_modes[0].xres * 3;
 192                yuv = false;
 193                break;
 194        case MIPI_BGR666:
 195                pctype = 0xb;
 196                datatype = MIPI_DSI_PACKED_PIXEL_STREAM_18;
 197                pixfmt = MIPI_DCS_PIXEL_FMT_18BIT;
 198                linelength = (ch->lcd_modes[0].xres * 18 + 7) / 8;
 199                yuv = false;
 200                break;
 201        case MIPI_YUYV:
 202                pctype = 4;
 203                datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16;
 204                pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
 205                linelength = ch->lcd_modes[0].xres * 2;
 206                yuv = true;
 207                break;
 208        case MIPI_UYVY:
 209                pctype = 5;
 210                datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16;
 211                pixfmt = MIPI_DCS_PIXEL_FMT_16BIT;
 212                linelength = ch->lcd_modes[0].xres * 2;
 213                yuv = true;
 214                break;
 215        case MIPI_YUV420_L:
 216                pctype = 6;
 217                datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12;
 218                pixfmt = MIPI_DCS_PIXEL_FMT_12BIT;
 219                linelength = (ch->lcd_modes[0].xres * 12 + 7) / 8;
 220                yuv = true;
 221                break;
 222        case MIPI_YUV420:
 223                pctype = 7;
 224                datatype = MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12;
 225                pixfmt = MIPI_DCS_PIXEL_FMT_12BIT;
 226                /* Length of U/V line */
 227                linelength = (ch->lcd_modes[0].xres + 1) / 2;
 228                yuv = true;
 229                break;
 230        default:
 231                return -EINVAL;
 232        }
 233
 234        if ((yuv && ch->interface_type != YUV422) ||
 235            (!yuv && ch->interface_type != RGB24))
 236                return -EINVAL;
 237
 238        if (!pdata->lane)
 239                return -EINVAL;
 240
 241        /* reset DSI link */
 242        iowrite32(0x00000001, base + SYSCTRL);
 243        /* Hold reset for 100 cycles of the slowest of bus, HS byte and LP clock */
 244        udelay(50);
 245        iowrite32(0x00000000, base + SYSCTRL);
 246
 247        /* setup DSI link */
 248
 249        /*
 250         * T_wakeup = 0x7000
 251         * T_hs-trail = 3
 252         * T_hs-prepare = 3
 253         * T_clk-trail = 3
 254         * T_clk-prepare = 2
 255         */
 256        iowrite32(0x70003332, base + TIMSET);
 257        /* no responses requested */
 258        iowrite32(0x00000000, base + RESREQSET0);
 259        /* request response to packets of type 0x28 */
 260        iowrite32(0x00000100, base + RESREQSET1);
 261        /* High-speed transmission timeout, default 0xffffffff */
 262        iowrite32(0x0fffffff, base + HSTTOVSET);
 263        /* LP reception timeout, default 0xffffffff */
 264        iowrite32(0x0fffffff, base + LPRTOVSET);
 265        /* Turn-around timeout, default 0xffffffff */
 266        iowrite32(0x0fffffff, base + TATOVSET);
 267        /* Peripheral reset timeout, default 0xffffffff */
 268        iowrite32(0x0fffffff, base + PRTOVSET);
 269        /* Interrupts not used, disable all */
 270        iowrite32(0, base + DSIINTE);
 271        /* DSI-Tx bias on */
 272        iowrite32(0x00000001, base + PHYCTRL);
 273        udelay(200);
 274        /* Deassert resets, power on */
 275        iowrite32(0x03070001 | pdata->phyctrl, base + PHYCTRL);
 276
 277        /*
 278         * Default = ULPS enable |
 279         *      Contention detection enabled |
 280         *      EoT packet transmission enable |
 281         *      CRC check enable |
 282         *      ECC check enable
 283         */
 284        bitmap_fill((unsigned long *)&tmp, pdata->lane);
 285        tmp |= 0x00003700;
 286        iowrite32(tmp, base + SYSCONF);
 287
 288        /* setup l-bridge */
 289
 290        /*
 291         * Enable transmission of all packets,
 292         * transmit LPS after each HS packet completion
 293         */
 294        iowrite32(0x00000006, mipi->linkbase + DTCTR);
 295        /* VSYNC width = 2 (<< 17) */
 296        iowrite32((ch->lcd_modes[0].vsync_len << pdata->vsynw_offset) |
 297                  (pdata->clksrc << 16) | (pctype << 12) | datatype,
 298                  mipi->linkbase + VMCTR1);
 299
 300        /*
 301         * Non-burst mode with sync pulses: VSE and HSE are output,
 302         * HSA period allowed, no commands in LP
 303         */
 304        vmctr2 = 0;
 305        if (pdata->flags & SH_MIPI_DSI_VSEE)
 306                vmctr2 |= 1 << 23;
 307        if (pdata->flags & SH_MIPI_DSI_HSEE)
 308                vmctr2 |= 1 << 22;
 309        if (pdata->flags & SH_MIPI_DSI_HSAE)
 310                vmctr2 |= 1 << 21;
 311        if (pdata->flags & SH_MIPI_DSI_BL2E)
 312                vmctr2 |= 1 << 17;
 313        if (pdata->flags & SH_MIPI_DSI_HSABM)
 314                vmctr2 |= 1 << 5;
 315        if (pdata->flags & SH_MIPI_DSI_HBPBM)
 316                vmctr2 |= 1 << 4;
 317        if (pdata->flags & SH_MIPI_DSI_HFPBM)
 318                vmctr2 |= 1 << 3;
 319        iowrite32(vmctr2, mipi->linkbase + VMCTR2);
 320
 321        /*
 322         * VMLEN1 = RGBLEN | HSALEN
 323         *
 324         * see
 325         *  Video mode - Blanking Packet setting
 326         */
 327        top = linelength << 16; /* RGBLEN */
 328        bottom = 0x00000001;
 329        if (pdata->flags & SH_MIPI_DSI_HSABM) /* HSALEN */
 330                bottom = (pdata->lane * ch->lcd_modes[0].hsync_len) - 10;
 331        iowrite32(top | bottom , mipi->linkbase + VMLEN1);
 332
 333        /*
 334         * VMLEN2 = HBPLEN | HFPLEN
 335         *
 336         * see
 337         *  Video mode - Blanking Packet setting
 338         */
 339        top     = 0x00010000;
 340        bottom  = 0x00000001;
 341        delay   = 0;
 342
 343        div = 1;        /* HSbyteCLK is calculation base
 344                         * HS4divCLK = HSbyteCLK/2
 345                         * HS6divCLK is not supported for now */
 346        if (pdata->flags & SH_MIPI_DSI_HS4divCLK)
 347                div = 2;
 348
 349        if (pdata->flags & SH_MIPI_DSI_HFPBM) { /* HBPLEN */
 350                top = ch->lcd_modes[0].hsync_len + ch->lcd_modes[0].left_margin;
 351                top = ((pdata->lane * top / div) - 10) << 16;
 352        }
 353        if (pdata->flags & SH_MIPI_DSI_HBPBM) { /* HFPLEN */
 354                bottom = ch->lcd_modes[0].right_margin;
 355                bottom = (pdata->lane * bottom / div) - 12;
 356        }
 357
 358        bpp = linelength / ch->lcd_modes[0].xres; /* byte / pixel */
 359        if ((pdata->lane / div) > bpp) {
 360                tmp = ch->lcd_modes[0].xres / bpp; /* output cycle */
 361                tmp = ch->lcd_modes[0].xres - tmp; /* (input - output) cycle */
 362                delay = (pdata->lane * tmp);
 363        }
 364
 365        iowrite32(top | (bottom + delay) , mipi->linkbase + VMLEN2);
 366
 367        msleep(5);
 368
 369        /* setup LCD panel */
 370
 371        /* cf. drivers/video/omap/lcd_mipid.c */
 372        sh_mipi_dcs(ch->chan, MIPI_DCS_EXIT_SLEEP_MODE);
 373        msleep(120);
 374        /*
 375         * [7] - Page Address Mode
 376         * [6] - Column Address Mode
 377         * [5] - Page / Column Address Mode
 378         * [4] - Display Device Line Refresh Order
 379         * [3] - RGB/BGR Order
 380         * [2] - Display Data Latch Data Order
 381         * [1] - Flip Horizontal
 382         * [0] - Flip Vertical
 383         */
 384        sh_mipi_dcs_param(ch->chan, MIPI_DCS_SET_ADDRESS_MODE, 0x00);
 385        /* cf. set_data_lines() */
 386        sh_mipi_dcs_param(ch->chan, MIPI_DCS_SET_PIXEL_FORMAT,
 387                          pixfmt << 4);
 388        sh_mipi_dcs(ch->chan, MIPI_DCS_SET_DISPLAY_ON);
 389
 390        /* Enable timeout counters */
 391        iowrite32(0x00000f00, base + DSICTRL);
 392
 393        return 0;
 394}
 395
 396static int mipi_display_on(struct sh_mobile_lcdc_entity *entity)
 397{
 398        struct sh_mipi *mipi = to_sh_mipi(entity);
 399        struct sh_mipi_dsi_info *pdata = mipi->pdev->dev.platform_data;
 400        int ret;
 401
 402        pm_runtime_get_sync(&mipi->pdev->dev);
 403
 404        ret = pdata->set_dot_clock(mipi->pdev, mipi->base, 1);
 405        if (ret < 0)
 406                goto mipi_display_on_fail1;
 407
 408        ret = sh_mipi_setup(mipi, pdata);
 409        if (ret < 0)
 410                goto mipi_display_on_fail2;
 411
 412        sh_mipi_dsi_enable(mipi, true);
 413
 414        return SH_MOBILE_LCDC_DISPLAY_CONNECTED;
 415
 416mipi_display_on_fail1:
 417        pm_runtime_put_sync(&mipi->pdev->dev);
 418mipi_display_on_fail2:
 419        pdata->set_dot_clock(mipi->pdev, mipi->base, 0);
 420
 421        return ret;
 422}
 423
 424static void mipi_display_off(struct sh_mobile_lcdc_entity *entity)
 425{
 426        struct sh_mipi *mipi = to_sh_mipi(entity);
 427        struct sh_mipi_dsi_info *pdata = mipi->pdev->dev.platform_data;
 428
 429        sh_mipi_dsi_enable(mipi, false);
 430
 431        pdata->set_dot_clock(mipi->pdev, mipi->base, 0);
 432
 433        pm_runtime_put_sync(&mipi->pdev->dev);
 434}
 435
 436static const struct sh_mobile_lcdc_entity_ops mipi_ops = {
 437        .display_on = mipi_display_on,
 438        .display_off = mipi_display_off,
 439};
 440
 441static int __init sh_mipi_probe(struct platform_device *pdev)
 442{
 443        struct sh_mipi *mipi;
 444        struct sh_mipi_dsi_info *pdata = pdev->dev.platform_data;
 445        struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 446        struct resource *res2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
 447        unsigned long rate, f_current;
 448        int idx = pdev->id, ret;
 449
 450        if (!res || !res2 || idx >= ARRAY_SIZE(mipi_dsi) || !pdata)
 451                return -ENODEV;
 452
 453        if (!pdata->set_dot_clock)
 454                return -EINVAL;
 455
 456        mutex_lock(&array_lock);
 457        if (idx < 0)
 458                for (idx = 0; idx < ARRAY_SIZE(mipi_dsi) && mipi_dsi[idx]; idx++)
 459                        ;
 460
 461        if (idx == ARRAY_SIZE(mipi_dsi)) {
 462                ret = -EBUSY;
 463                goto efindslot;
 464        }
 465
 466        mipi = kzalloc(sizeof(*mipi), GFP_KERNEL);
 467        if (!mipi) {
 468                ret = -ENOMEM;
 469                goto ealloc;
 470        }
 471
 472        mipi->entity.owner = THIS_MODULE;
 473        mipi->entity.ops = &mipi_ops;
 474
 475        if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
 476                dev_err(&pdev->dev, "MIPI register region already claimed\n");
 477                ret = -EBUSY;
 478                goto ereqreg;
 479        }
 480
 481        mipi->base = ioremap(res->start, resource_size(res));
 482        if (!mipi->base) {
 483                ret = -ENOMEM;
 484                goto emap;
 485        }
 486
 487        if (!request_mem_region(res2->start, resource_size(res2), pdev->name)) {
 488                dev_err(&pdev->dev, "MIPI register region 2 already claimed\n");
 489                ret = -EBUSY;
 490                goto ereqreg2;
 491        }
 492
 493        mipi->linkbase = ioremap(res2->start, resource_size(res2));
 494        if (!mipi->linkbase) {
 495                ret = -ENOMEM;
 496                goto emap2;
 497        }
 498
 499        mipi->pdev = pdev;
 500
 501        mipi->dsit_clk = clk_get(&pdev->dev, "dsit_clk");
 502        if (IS_ERR(mipi->dsit_clk)) {
 503                ret = PTR_ERR(mipi->dsit_clk);
 504                goto eclktget;
 505        }
 506
 507        f_current = clk_get_rate(mipi->dsit_clk);
 508        /* 80MHz required by the datasheet */
 509        rate = clk_round_rate(mipi->dsit_clk, 80000000);
 510        if (rate > 0 && rate != f_current)
 511                ret = clk_set_rate(mipi->dsit_clk, rate);
 512        else
 513                ret = rate;
 514        if (ret < 0)
 515                goto esettrate;
 516
 517        dev_dbg(&pdev->dev, "DSI-T clk %lu -> %lu\n", f_current, rate);
 518
 519        ret = clk_enable(mipi->dsit_clk);
 520        if (ret < 0)
 521                goto eclkton;
 522
 523        mipi_dsi[idx] = mipi;
 524
 525        pm_runtime_enable(&pdev->dev);
 526        pm_runtime_resume(&pdev->dev);
 527
 528        mutex_unlock(&array_lock);
 529        platform_set_drvdata(pdev, &mipi->entity);
 530
 531        return 0;
 532
 533eclkton:
 534esettrate:
 535        clk_put(mipi->dsit_clk);
 536eclktget:
 537        iounmap(mipi->linkbase);
 538emap2:
 539        release_mem_region(res2->start, resource_size(res2));
 540ereqreg2:
 541        iounmap(mipi->base);
 542emap:
 543        release_mem_region(res->start, resource_size(res));
 544ereqreg:
 545        kfree(mipi);
 546ealloc:
 547efindslot:
 548        mutex_unlock(&array_lock);
 549
 550        return ret;
 551}
 552
 553static int __devexit sh_mipi_remove(struct platform_device *pdev)
 554{
 555        struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 556        struct resource *res2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
 557        struct sh_mipi *mipi = to_sh_mipi(platform_get_drvdata(pdev));
 558        int i, ret;
 559
 560        mutex_lock(&array_lock);
 561
 562        for (i = 0; i < ARRAY_SIZE(mipi_dsi) && mipi_dsi[i] != mipi; i++)
 563                ;
 564
 565        if (i == ARRAY_SIZE(mipi_dsi)) {
 566                ret = -EINVAL;
 567        } else {
 568                ret = 0;
 569                mipi_dsi[i] = NULL;
 570        }
 571
 572        mutex_unlock(&array_lock);
 573
 574        if (ret < 0)
 575                return ret;
 576
 577        pm_runtime_disable(&pdev->dev);
 578        clk_disable(mipi->dsit_clk);
 579        clk_put(mipi->dsit_clk);
 580
 581        iounmap(mipi->linkbase);
 582        if (res2)
 583                release_mem_region(res2->start, resource_size(res2));
 584        iounmap(mipi->base);
 585        if (res)
 586                release_mem_region(res->start, resource_size(res));
 587        platform_set_drvdata(pdev, NULL);
 588        kfree(mipi);
 589
 590        return 0;
 591}
 592
 593static struct platform_driver sh_mipi_driver = {
 594        .remove         = __devexit_p(sh_mipi_remove),
 595        .shutdown       = sh_mipi_shutdown,
 596        .driver = {
 597                .name   = "sh-mipi-dsi",
 598        },
 599};
 600
 601static int __init sh_mipi_init(void)
 602{
 603        return platform_driver_probe(&sh_mipi_driver, sh_mipi_probe);
 604}
 605module_init(sh_mipi_init);
 606
 607static void __exit sh_mipi_exit(void)
 608{
 609        platform_driver_unregister(&sh_mipi_driver);
 610}
 611module_exit(sh_mipi_exit);
 612
 613MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
 614MODULE_DESCRIPTION("SuperH / ARM-shmobile MIPI DSI driver");
 615MODULE_LICENSE("GPL v2");
 616
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.