⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mx3fb.c

📁 Linux环境下视频显示卡设备的驱动程序源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
               if (sdc_init_panel(mx3fb, mode,                                  (PICOS2KHZ(fbi->var.pixclock)) * 1000UL,                                  fbi->var.xres, fbi->var.yres,                                  (fbi->var.sync & FB_SYNC_SWAP_RGB) ?                                  IPU_PIX_FMT_BGR666 : IPU_PIX_FMT_RGB666,                                  fbi->var.left_margin,                                  fbi->var.hsync_len,                                  fbi->var.right_margin +                                  fbi->var.hsync_len,                                  fbi->var.upper_margin,                                  fbi->var.vsync_len,                                  fbi->var.lower_margin +                                  fbi->var.vsync_len, sig_cfg) != 0) {                       mutex_unlock(&mx3_fbi->mutex);                       dev_err(fbi->device,                               "mx3fb: Error initializing panel.\n");                       return -EINVAL;               }       }       sdc_set_window_pos(mx3fb, mx3_fbi->ipu_ch, 0, 0);       mx3_fbi->cur_ipu_buf    = 0;       video->out_pixel_fmt    = bpp_to_pixfmt(fbi->var.bits_per_pixel);       video->out_width        = fbi->var.xres;       video->out_height       = fbi->var.yres;       video->out_stride       = fbi->var.xres_virtual;       if (mx3_fbi->blank == FB_BLANK_UNBLANK)               sdc_enable_channel(mx3_fbi);       mutex_unlock(&mx3_fbi->mutex);       return 0;}/** * mx3fb_check_var() - check and adjust framebuffer variable parameters. * @var:       framebuffer variable parameters * @fbi:       framebuffer information pointer */static int mx3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi){       struct mx3fb_info *mx3_fbi = fbi->par;       u32 vtotal;       u32 htotal;       dev_dbg(fbi->device, "%s\n", __func__);       if (var->xres_virtual < var->xres)               var->xres_virtual = var->xres;       if (var->yres_virtual < var->yres)               var->yres_virtual = var->yres;       if ((var->bits_per_pixel != 32) && (var->bits_per_pixel != 24) &&           (var->bits_per_pixel != 16))               var->bits_per_pixel = default_bpp;       switch (var->bits_per_pixel) {       case 16:               var->red.length = 5;               var->red.offset = 11;               var->red.msb_right = 0;               var->green.length = 6;               var->green.offset = 5;               var->green.msb_right = 0;               var->blue.length = 5;               var->blue.offset = 0;               var->blue.msb_right = 0;               var->transp.length = 0;               var->transp.offset = 0;               var->transp.msb_right = 0;               break;       case 24:               var->red.length = 8;               var->red.offset = 16;               var->red.msb_right = 0;               var->green.length = 8;               var->green.offset = 8;               var->green.msb_right = 0;               var->blue.length = 8;               var->blue.offset = 0;               var->blue.msb_right = 0;               var->transp.length = 0;               var->transp.offset = 0;               var->transp.msb_right = 0;               break;       case 32:               var->red.length = 8;               var->red.offset = 16;               var->red.msb_right = 0;               var->green.length = 8;               var->green.offset = 8;               var->green.msb_right = 0;               var->blue.length = 8;               var->blue.offset = 0;               var->blue.msb_right = 0;               var->transp.length = 8;               var->transp.offset = 24;               var->transp.msb_right = 0;               break;       }       if (var->pixclock < 1000) {               htotal = var->xres + var->right_margin + var->hsync_len +                   var->left_margin;               vtotal = var->yres + var->lower_margin + var->vsync_len +                   var->upper_margin;               var->pixclock = (vtotal * htotal * 6UL) / 100UL;               var->pixclock = KHZ2PICOS(var->pixclock);               dev_dbg(fbi->device, "pixclock set for 60Hz refresh = %u ps\n",                       var->pixclock);       }       var->height = -1;       var->width = -1;       var->grayscale = 0;       /* Preserve sync flags */       var->sync |= mx3_fbi->sync;       mx3_fbi->sync |= var->sync;       return 0;}static u32 chan_to_field(unsigned int chan, struct fb_bitfield *bf){       chan &= 0xffff;       chan >>= 16 - bf->length;       return chan << bf->offset;}static int mx3fb_setcolreg(unsigned int regno, unsigned int red,                          unsigned int green, unsigned int blue,                          unsigned int trans, struct fb_info *fbi){       struct mx3fb_info *mx3_fbi = fbi->par;       u32 val;       int ret = 1;       dev_dbg(fbi->device, "%s\n", __func__);       mutex_lock(&mx3_fbi->mutex);       /*        * If greyscale is true, then we convert the RGB value        * to greyscale no matter what visual we are using.        */       if (fbi->var.grayscale)               red = green = blue = (19595 * red + 38470 * green +                                     7471 * blue) >> 16;       switch (fbi->fix.visual) {       case FB_VISUAL_TRUECOLOR:               /*                * 16-bit True Colour.  We encode the RGB value                * according to the RGB bitfield information.                */               if (regno < 16) {                       u32 *pal = fbi->pseudo_palette;                       val = chan_to_field(red, &fbi->var.red);                       val |= chan_to_field(green, &fbi->var.green);                       val |= chan_to_field(blue, &fbi->var.blue);                       pal[regno] = val;                       ret = 0;               }               break;       case FB_VISUAL_STATIC_PSEUDOCOLOR:       case FB_VISUAL_PSEUDOCOLOR:               break;       }       mutex_unlock(&mx3_fbi->mutex);       return ret;}/** * mx3fb_blank() - blank the display. */static int mx3fb_blank(int blank, struct fb_info *fbi){       struct mx3fb_info *mx3_fbi = fbi->par;       struct mx3fb_data *mx3fb = mx3_fbi->mx3fb;       dev_dbg(fbi->device, "%s\n", __func__);       dev_dbg(fbi->device, "blank = %d\n", blank);       if (mx3_fbi->blank == blank)               return 0;       mutex_lock(&mx3_fbi->mutex);       mx3_fbi->blank = blank;       switch (blank) {       case FB_BLANK_POWERDOWN:       case FB_BLANK_VSYNC_SUSPEND:       case FB_BLANK_HSYNC_SUSPEND:       case FB_BLANK_NORMAL:               sdc_disable_channel(mx3_fbi);               sdc_set_brightness(mx3fb, 0);               break;       case FB_BLANK_UNBLANK:               sdc_enable_channel(mx3_fbi);               sdc_set_brightness(mx3fb, mx3fb->backlight_level);               break;       }       mutex_unlock(&mx3_fbi->mutex);       return 0;}/** * mx3fb_pan_display() - pan or wrap the display * @var:       variable screen buffer information. * @info:      framebuffer information pointer. * * We look only at xoffset, yoffset and the FB_VMODE_YWRAP flag */static int mx3fb_pan_display(struct fb_var_screeninfo *var,                            struct fb_info *fbi){       struct mx3fb_info *mx3_fbi = fbi->par;       u32 y_bottom;       unsigned long base;       off_t offset;       dma_cookie_t cookie;       struct scatterlist *sg = mx3_fbi->sg;       struct dma_chan *dma_chan = &mx3_fbi->idmac_channel->dma_chan;       struct dma_async_tx_descriptor *txd;       int ret;       dev_dbg(fbi->device, "%s [%c]\n", __func__,               list_empty(&mx3_fbi->idmac_channel->queue) ? '-' : '+');       if (var->xoffset > 0) {               dev_dbg(fbi->device, "x panning not supported\n");               return -EINVAL;       }       if (fbi->var.xoffset == var->xoffset &&           fbi->var.yoffset == var->yoffset)               return 0;       /* No change, do nothing */       y_bottom = var->yoffset;       if (!(var->vmode & FB_VMODE_YWRAP))               y_bottom += var->yres;       if (y_bottom > fbi->var.yres_virtual)               return -EINVAL;       mutex_lock(&mx3_fbi->mutex);       offset = (var->yoffset * var->xres_virtual + var->xoffset) *               (var->bits_per_pixel / 8);       base = fbi->fix.smem_start + offset;       dev_dbg(fbi->device, "Updating SDC BG buf %d address=0x%08lX\n",               mx3_fbi->cur_ipu_buf, base);       /*        * We enable the End of Frame interrupt, which will free a tx-descriptor,        * which we will need for the next device_prep_slave_sg(). The        * IRQ-handler will disable the IRQ again.        */       init_completion(&mx3_fbi->flip_cmpl);       enable_irq(mx3_fbi->idmac_channel->eof_irq);       ret = wait_for_completion_timeout(&mx3_fbi->flip_cmpl, HZ / 10);       if (ret <= 0) {               mutex_unlock(&mx3_fbi->mutex);               dev_info(fbi->device, "Panning failed due to %s\n", ret < 0 ?                        "user interrupt" : "timeout");               return ret ? : -ETIMEDOUT;       }       mx3_fbi->cur_ipu_buf = !mx3_fbi->cur_ipu_buf;       sg_dma_address(&sg[mx3_fbi->cur_ipu_buf]) = base;       sg_set_page(&sg[mx3_fbi->cur_ipu_buf],                   virt_to_page(fbi->screen_base + offset), fbi->fix.smem_len,                   offset_in_page(fbi->screen_base + offset));       txd = dma_chan->device->device_prep_slave_sg(dma_chan, sg +               mx3_fbi->cur_ipu_buf, 1, DMA_TO_DEVICE, DMA_PREP_INTERRUPT);       if (!txd) {               dev_err(fbi->device,                       "Error preparing a DMA transaction descriptor.\n");               mutex_unlock(&mx3_fbi->mutex);               return -EIO;       }       txd->callback_param     = txd;       txd->callback           = mx3fb_dma_done;       /*        * Emulate original mx3fb behaviour: each new call to idmac_tx_submit()        * should switch to another buffer        */       cookie = txd->tx_submit(txd);       dev_dbg(fbi->device, "%d: Submit %p #%d\n", __LINE__, txd, cookie);       if (cookie < 0) {               dev_err(fbi->device,                       "Error updating SDC buf %d to address=0x%08lX\n",                       mx3_fbi->cur_ipu_buf, base);               mutex_unlock(&mx3_fbi->mutex);               return -EIO;       }       if (mx3_fbi->txd)               async_tx_ack(mx3_fbi->txd);       mx3_fbi->txd = txd;       fbi->var.xoffset = var->xoffset;       fbi->var.yoffset = var->yoffset;       if (var->vmode & FB_VMODE_YWRAP)               fbi->var.vmode |= FB_VMODE_YWRAP;       else               fbi->var.vmode &= ~FB_VMODE_YWRAP;       mutex_unlock(&mx3_fbi->mutex);       dev_dbg(fbi->device, "Update complete\n");       return 0;}/* * This structure contains the pointers to the control functions that are * invoked by the core framebuffer driver to perform operations like * blitting, rectangle filling, copy regions and cursor definition. */static struct fb_ops mx3fb_ops = {       .owner = THIS_MODULE,       .fb_set_par = mx3fb_set_par,       .fb_check_var = mx3fb_check_var,       .fb_setcolreg = mx3fb_setcolreg,       .fb_pan_display = mx3fb_pan_display,       .fb_fillrect = cfb_fillrect,       .fb_copyarea = cfb_copyarea,       .fb_imageblit = cfb_imageblit,       .fb_blank = mx3fb_blank,};#ifdef CONFIG_PM/* * Power management hooks.      Note that we won't be called from IRQ context, * unlike the blank functions above, so we may sleep. *//* * Suspends the framebuffer and blanks the screen. Power management support */static int mx3fb_suspend(struct platform_device *pdev, pm_message_t state){       struct mx3fb_data *drv_data = platform_get_drvdata(pdev);       struct mx3fb_info *mx3_fbi = drv_data->fbi->par;       acquire_console_sem();       fb_set_suspend(drv_data->fbi, 1);       release_console_sem();       if (mx3_fbi->blank == FB_BLANK_UNBLANK) {               sdc_disable_channel(mx3_fbi);               sdc_set_brightness(mx3fb, 0);       }       return 0;}/* * Resumes the framebuffer and unblanks the screen. Power management support */static int mx3fb_resume(struct platform_device *pdev)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -