root/drivers/media/platform/vivid/vivid-osd.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. vivid_clear_fb
  2. vivid_fb_ioctl
  3. vivid_fb_set_var
  4. vivid_fb_get_fix
  5. _vivid_fb_check_var
  6. vivid_fb_check_var
  7. vivid_fb_pan_display
  8. vivid_fb_set_par
  9. vivid_fb_setcolreg
  10. vivid_fb_blank
  11. vivid_fb_init_vidmode
  12. vivid_fb_release_buffers
  13. vivid_fb_init

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * vivid-osd.c - osd support for testing overlays.
   4  *
   5  * Copyright 2014 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
   6  */
   7 
   8 #include <linux/module.h>
   9 #include <linux/errno.h>
  10 #include <linux/kernel.h>
  11 #include <linux/init.h>
  12 #include <linux/sched.h>
  13 #include <linux/slab.h>
  14 #include <linux/font.h>
  15 #include <linux/mutex.h>
  16 #include <linux/videodev2.h>
  17 #include <linux/kthread.h>
  18 #include <linux/freezer.h>
  19 #include <linux/fb.h>
  20 #include <media/videobuf2-vmalloc.h>
  21 #include <media/v4l2-device.h>
  22 #include <media/v4l2-ioctl.h>
  23 #include <media/v4l2-ctrls.h>
  24 #include <media/v4l2-fh.h>
  25 #include <media/v4l2-event.h>
  26 #include <media/v4l2-common.h>
  27 
  28 #include "vivid-core.h"
  29 #include "vivid-osd.h"
  30 
  31 #define MAX_OSD_WIDTH  720
  32 #define MAX_OSD_HEIGHT 576
  33 
  34 /*
  35  * Order: white, yellow, cyan, green, magenta, red, blue, black,
  36  * and same again with the alpha bit set (if any)
  37  */
  38 static const u16 rgb555[16] = {
  39         0x7fff, 0x7fe0, 0x03ff, 0x03e0, 0x7c1f, 0x7c00, 0x001f, 0x0000,
  40         0xffff, 0xffe0, 0x83ff, 0x83e0, 0xfc1f, 0xfc00, 0x801f, 0x8000
  41 };
  42 
  43 static const u16 rgb565[16] = {
  44         0xffff, 0xffe0, 0x07ff, 0x07e0, 0xf81f, 0xf800, 0x001f, 0x0000,
  45         0xffff, 0xffe0, 0x07ff, 0x07e0, 0xf81f, 0xf800, 0x001f, 0x0000
  46 };
  47 
  48 void vivid_clear_fb(struct vivid_dev *dev)
  49 {
  50         void *p = dev->video_vbase;
  51         const u16 *rgb = rgb555;
  52         unsigned x, y;
  53 
  54         if (dev->fb_defined.green.length == 6)
  55                 rgb = rgb565;
  56 
  57         for (y = 0; y < dev->display_height; y++) {
  58                 u16 *d = p;
  59 
  60                 for (x = 0; x < dev->display_width; x++)
  61                         d[x] = rgb[(y / 16 + x / 16) % 16];
  62                 p += dev->display_byte_stride;
  63         }
  64 }
  65 
  66 /* --------------------------------------------------------------------- */
  67 
  68 static int vivid_fb_ioctl(struct fb_info *info, unsigned cmd, unsigned long arg)
  69 {
  70         struct vivid_dev *dev = (struct vivid_dev *)info->par;
  71 
  72         switch (cmd) {
  73         case FBIOGET_VBLANK: {
  74                 struct fb_vblank vblank;
  75 
  76                 memset(&vblank, 0, sizeof(vblank));
  77                 vblank.flags = FB_VBLANK_HAVE_COUNT | FB_VBLANK_HAVE_VCOUNT |
  78                         FB_VBLANK_HAVE_VSYNC;
  79                 vblank.count = 0;
  80                 vblank.vcount = 0;
  81                 vblank.hcount = 0;
  82                 if (copy_to_user((void __user *)arg, &vblank, sizeof(vblank)))
  83                         return -EFAULT;
  84                 return 0;
  85         }
  86 
  87         default:
  88                 dprintk(dev, 1, "Unknown ioctl %08x\n", cmd);
  89                 return -EINVAL;
  90         }
  91         return 0;
  92 }
  93 
  94 /* Framebuffer device handling */
  95 
  96 static int vivid_fb_set_var(struct vivid_dev *dev, struct fb_var_screeninfo *var)
  97 {
  98         dprintk(dev, 1, "vivid_fb_set_var\n");
  99 
 100         if (var->bits_per_pixel != 16) {
 101                 dprintk(dev, 1, "vivid_fb_set_var - Invalid bpp\n");
 102                 return -EINVAL;
 103         }
 104         dev->display_byte_stride = var->xres * dev->bytes_per_pixel;
 105 
 106         return 0;
 107 }
 108 
 109 static int vivid_fb_get_fix(struct vivid_dev *dev, struct fb_fix_screeninfo *fix)
 110 {
 111         dprintk(dev, 1, "vivid_fb_get_fix\n");
 112         memset(fix, 0, sizeof(struct fb_fix_screeninfo));
 113         strscpy(fix->id, "vioverlay fb", sizeof(fix->id));
 114         fix->smem_start = dev->video_pbase;
 115         fix->smem_len = dev->video_buffer_size;
 116         fix->type = FB_TYPE_PACKED_PIXELS;
 117         fix->visual = FB_VISUAL_TRUECOLOR;
 118         fix->xpanstep = 1;
 119         fix->ypanstep = 1;
 120         fix->ywrapstep = 0;
 121         fix->line_length = dev->display_byte_stride;
 122         fix->accel = FB_ACCEL_NONE;
 123         return 0;
 124 }
 125 
 126 /* Check the requested display mode, returning -EINVAL if we can't
 127    handle it. */
 128 
 129 static int _vivid_fb_check_var(struct fb_var_screeninfo *var, struct vivid_dev *dev)
 130 {
 131         dprintk(dev, 1, "vivid_fb_check_var\n");
 132 
 133         var->bits_per_pixel = 16;
 134         if (var->green.length == 5) {
 135                 var->red.offset = 10;
 136                 var->red.length = 5;
 137                 var->green.offset = 5;
 138                 var->green.length = 5;
 139                 var->blue.offset = 0;
 140                 var->blue.length = 5;
 141                 var->transp.offset = 15;
 142                 var->transp.length = 1;
 143         } else {
 144                 var->red.offset = 11;
 145                 var->red.length = 5;
 146                 var->green.offset = 5;
 147                 var->green.length = 6;
 148                 var->blue.offset = 0;
 149                 var->blue.length = 5;
 150                 var->transp.offset = 0;
 151                 var->transp.length = 0;
 152         }
 153         var->xoffset = var->yoffset = 0;
 154         var->left_margin = var->upper_margin = 0;
 155         var->nonstd = 0;
 156 
 157         var->vmode &= ~FB_VMODE_MASK;
 158         var->vmode |= FB_VMODE_NONINTERLACED;
 159 
 160         /* Dummy values */
 161         var->hsync_len = 24;
 162         var->vsync_len = 2;
 163         var->pixclock = 84316;
 164         var->right_margin = 776;
 165         var->lower_margin = 591;
 166         return 0;
 167 }
 168 
 169 static int vivid_fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 170 {
 171         struct vivid_dev *dev = (struct vivid_dev *) info->par;
 172 
 173         dprintk(dev, 1, "vivid_fb_check_var\n");
 174         return _vivid_fb_check_var(var, dev);
 175 }
 176 
 177 static int vivid_fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
 178 {
 179         return 0;
 180 }
 181 
 182 static int vivid_fb_set_par(struct fb_info *info)
 183 {
 184         int rc = 0;
 185         struct vivid_dev *dev = (struct vivid_dev *) info->par;
 186 
 187         dprintk(dev, 1, "vivid_fb_set_par\n");
 188 
 189         rc = vivid_fb_set_var(dev, &info->var);
 190         vivid_fb_get_fix(dev, &info->fix);
 191         return rc;
 192 }
 193 
 194 static int vivid_fb_setcolreg(unsigned regno, unsigned red, unsigned green,
 195                                 unsigned blue, unsigned transp,
 196                                 struct fb_info *info)
 197 {
 198         u32 color, *palette;
 199 
 200         if (regno >= info->cmap.len)
 201                 return -EINVAL;
 202 
 203         color = ((transp & 0xFF00) << 16) | ((red & 0xFF00) << 8) |
 204                  (green & 0xFF00) | ((blue & 0xFF00) >> 8);
 205         if (regno >= 16)
 206                 return -EINVAL;
 207 
 208         palette = info->pseudo_palette;
 209         if (info->var.bits_per_pixel == 16) {
 210                 switch (info->var.green.length) {
 211                 case 6:
 212                         color = (red & 0xf800) |
 213                                 ((green & 0xfc00) >> 5) |
 214                                 ((blue & 0xf800) >> 11);
 215                         break;
 216                 case 5:
 217                         color = ((red & 0xf800) >> 1) |
 218                                 ((green & 0xf800) >> 6) |
 219                                 ((blue & 0xf800) >> 11) |
 220                                 (transp ? 0x8000 : 0);
 221                         break;
 222                 }
 223         }
 224         palette[regno] = color;
 225         return 0;
 226 }
 227 
 228 /* We don't really support blanking. All this does is enable or
 229    disable the OSD. */
 230 static int vivid_fb_blank(int blank_mode, struct fb_info *info)
 231 {
 232         struct vivid_dev *dev = (struct vivid_dev *)info->par;
 233 
 234         dprintk(dev, 1, "Set blanking mode : %d\n", blank_mode);
 235         switch (blank_mode) {
 236         case FB_BLANK_UNBLANK:
 237                 break;
 238         case FB_BLANK_NORMAL:
 239         case FB_BLANK_HSYNC_SUSPEND:
 240         case FB_BLANK_VSYNC_SUSPEND:
 241         case FB_BLANK_POWERDOWN:
 242                 break;
 243         }
 244         return 0;
 245 }
 246 
 247 static struct fb_ops vivid_fb_ops = {
 248         .owner = THIS_MODULE,
 249         .fb_check_var   = vivid_fb_check_var,
 250         .fb_set_par     = vivid_fb_set_par,
 251         .fb_setcolreg   = vivid_fb_setcolreg,
 252         .fb_fillrect    = cfb_fillrect,
 253         .fb_copyarea    = cfb_copyarea,
 254         .fb_imageblit   = cfb_imageblit,
 255         .fb_cursor      = NULL,
 256         .fb_ioctl       = vivid_fb_ioctl,
 257         .fb_pan_display = vivid_fb_pan_display,
 258         .fb_blank       = vivid_fb_blank,
 259 };
 260 
 261 /* Initialization */
 262 
 263 
 264 /* Setup our initial video mode */
 265 static int vivid_fb_init_vidmode(struct vivid_dev *dev)
 266 {
 267         struct v4l2_rect start_window;
 268 
 269         /* Color mode */
 270 
 271         dev->bits_per_pixel = 16;
 272         dev->bytes_per_pixel = dev->bits_per_pixel / 8;
 273 
 274         start_window.width = MAX_OSD_WIDTH;
 275         start_window.left = 0;
 276 
 277         dev->display_byte_stride = start_window.width * dev->bytes_per_pixel;
 278 
 279         /* Vertical size & position */
 280 
 281         start_window.height = MAX_OSD_HEIGHT;
 282         start_window.top = 0;
 283 
 284         dev->display_width = start_window.width;
 285         dev->display_height = start_window.height;
 286 
 287         /* Generate a valid fb_var_screeninfo */
 288 
 289         dev->fb_defined.xres = dev->display_width;
 290         dev->fb_defined.yres = dev->display_height;
 291         dev->fb_defined.xres_virtual = dev->display_width;
 292         dev->fb_defined.yres_virtual = dev->display_height;
 293         dev->fb_defined.bits_per_pixel = dev->bits_per_pixel;
 294         dev->fb_defined.vmode = FB_VMODE_NONINTERLACED;
 295         dev->fb_defined.left_margin = start_window.left + 1;
 296         dev->fb_defined.upper_margin = start_window.top + 1;
 297         dev->fb_defined.accel_flags = FB_ACCEL_NONE;
 298         dev->fb_defined.nonstd = 0;
 299         /* set default to 1:5:5:5 */
 300         dev->fb_defined.green.length = 5;
 301 
 302         /* We've filled in the most data, let the usual mode check
 303            routine fill in the rest. */
 304         _vivid_fb_check_var(&dev->fb_defined, dev);
 305 
 306         /* Generate valid fb_fix_screeninfo */
 307 
 308         vivid_fb_get_fix(dev, &dev->fb_fix);
 309 
 310         /* Generate valid fb_info */
 311 
 312         dev->fb_info.node = -1;
 313         dev->fb_info.flags = FBINFO_FLAG_DEFAULT;
 314         dev->fb_info.fbops = &vivid_fb_ops;
 315         dev->fb_info.par = dev;
 316         dev->fb_info.var = dev->fb_defined;
 317         dev->fb_info.fix = dev->fb_fix;
 318         dev->fb_info.screen_base = (u8 __iomem *)dev->video_vbase;
 319         dev->fb_info.fbops = &vivid_fb_ops;
 320 
 321         /* Supply some monitor specs. Bogus values will do for now */
 322         dev->fb_info.monspecs.hfmin = 8000;
 323         dev->fb_info.monspecs.hfmax = 70000;
 324         dev->fb_info.monspecs.vfmin = 10;
 325         dev->fb_info.monspecs.vfmax = 100;
 326 
 327         /* Allocate color map */
 328         if (fb_alloc_cmap(&dev->fb_info.cmap, 256, 1)) {
 329                 pr_err("abort, unable to alloc cmap\n");
 330                 return -ENOMEM;
 331         }
 332 
 333         /* Allocate the pseudo palette */
 334         dev->fb_info.pseudo_palette = kmalloc_array(16, sizeof(u32), GFP_KERNEL);
 335 
 336         return dev->fb_info.pseudo_palette ? 0 : -ENOMEM;
 337 }
 338 
 339 /* Release any memory we've grabbed */
 340 void vivid_fb_release_buffers(struct vivid_dev *dev)
 341 {
 342         if (dev->video_vbase == NULL)
 343                 return;
 344 
 345         /* Release cmap */
 346         if (dev->fb_info.cmap.len)
 347                 fb_dealloc_cmap(&dev->fb_info.cmap);
 348 
 349         /* Release pseudo palette */
 350         kfree(dev->fb_info.pseudo_palette);
 351         kfree(dev->video_vbase);
 352 }
 353 
 354 /* Initialize the specified card */
 355 
 356 int vivid_fb_init(struct vivid_dev *dev)
 357 {
 358         int ret;
 359 
 360         dev->video_buffer_size = MAX_OSD_HEIGHT * MAX_OSD_WIDTH * 2;
 361         dev->video_vbase = kzalloc(dev->video_buffer_size, GFP_KERNEL | GFP_DMA32);
 362         if (dev->video_vbase == NULL)
 363                 return -ENOMEM;
 364         dev->video_pbase = virt_to_phys(dev->video_vbase);
 365 
 366         pr_info("Framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
 367                         dev->video_pbase, dev->video_vbase,
 368                         dev->video_buffer_size / 1024);
 369 
 370         /* Set the startup video mode information */
 371         ret = vivid_fb_init_vidmode(dev);
 372         if (ret) {
 373                 vivid_fb_release_buffers(dev);
 374                 return ret;
 375         }
 376 
 377         vivid_clear_fb(dev);
 378 
 379         /* Register the framebuffer */
 380         if (register_framebuffer(&dev->fb_info) < 0) {
 381                 vivid_fb_release_buffers(dev);
 382                 return -EINVAL;
 383         }
 384 
 385         /* Set the card to the requested mode */
 386         vivid_fb_set_par(&dev->fb_info);
 387         return 0;
 388 
 389 }

/* [<][>][^][v][top][bottom][index][help] */