drm/linux-core/nv50_fb.c

143 lines
3.3 KiB
C

/*
* Copyright (C) 2008 Maarten Maathuis.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#include "nv50_fb.h"
#include "nv50_lut.h"
#include "nv50_crtc.h"
#include "nv50_display.h"
static int nv50_fb_bind(struct nv50_crtc *crtc, struct nv50_fb_info *info)
{
int rval = 0;
NV50_DEBUG("\n");
if (!crtc || !info) {
DRM_ERROR("crtc %p info %p\n",crtc, info);
return -EINVAL;
}
if (!info->block || !info->width || !info->height || !info->depth || !info->bpp || !info->pitch) {
DRM_ERROR("block %p width %d height %d depth %d bpp %d pitch %d\n", info->block, info->width,
info->height, info->depth, info->bpp, info->pitch);
return -EINVAL;
}
crtc->fb->block = info->block;
crtc->fb->width = info->width;
crtc->fb->height = info->height;
crtc->fb->y = info->x;
crtc->fb->x = info->y;
crtc->fb->depth = info->depth;
crtc->fb->bpp = info->bpp;
crtc->fb->pitch = info->pitch;
/* update lut if needed */
if (crtc->fb->depth != crtc->lut->depth) {
int r_size = 0, g_size = 0, b_size = 0;
uint16_t *r_val, *g_val, *b_val;
int i;
switch (crtc->fb->depth) {
case 15:
r_size = 32;
g_size = 32;
b_size = 32;
break;
case 16:
r_size = 32;
g_size = 64;
b_size = 32;
break;
case 24:
default:
r_size = 256;
g_size = 256;
b_size = 256;
break;
}
r_val = kmalloc(r_size * sizeof(uint16_t), GFP_KERNEL);
g_val = kmalloc(g_size * sizeof(uint16_t), GFP_KERNEL);
b_val = kmalloc(b_size * sizeof(uint16_t), GFP_KERNEL);
if (!r_val || !g_val || !b_val)
return -ENOMEM;
/* Set the color indices. */
for (i = 0; i < r_size; i++) {
r_val[i] = i << 8;
}
for (i = 0; i < g_size; i++) {
g_val[i] = i << 8;
}
for (i = 0; i < b_size; i++) {
b_val[i] = i << 8;
}
rval = crtc->lut->set(crtc, r_val, g_val, b_val);
/* free before returning */
kfree(r_val);
kfree(g_val);
kfree(b_val);
if (rval != 0)
return rval;
}
return 0;
}
int nv50_fb_create(struct nv50_crtc *crtc)
{
if (!crtc)
return -EINVAL;
crtc->fb = kzalloc(sizeof(struct nv50_fb), GFP_KERNEL);
if (!crtc->fb)
return -ENOMEM;
crtc->fb->bind = nv50_fb_bind;
return 0;
}
int nv50_fb_destroy(struct nv50_crtc *crtc)
{
if (!crtc)
return -EINVAL;
kfree(crtc->fb);
crtc->fb = NULL;
return 0;
}