blob: 01f5a5fddfc873007e6a63323736c3bc1cd7bf0b [file] [log] [blame]
#include "drmP.h"
#include "drm.h"
#include "drm_crtc_helper.h"
#include <video/pm3fb.h>
#include "glint.h"
#include "glint_drv.h"
#include "glint_mode.h"
static void glint_crtc_load_lut(struct drm_crtc *crtc)
{
struct glint_crtc *glint_crtc = to_glint_crtc(crtc);
struct drm_device *dev = crtc->dev;
struct glint_device *gdev = dev->dev_private;
int i;
if (!crtc->enabled)
return;
for (i = 0; i < 256; i++) {
WREG8(PM3RD_PaletteWriteAddress, i);
WREG8(PM3RD_PaletteData, glint_crtc->lut_r[i]);
WREG8(PM3RD_PaletteData, glint_crtc->lut_b[i]);
WREG8(PM3RD_PaletteData, glint_crtc->lut_g[i]);
}
}
static void glint_crtc_dpms(struct drm_crtc *crtc, int mode)
{
struct glint_crtc *glint_crtc = to_glint_crtc(crtc);
struct drm_device *dev = crtc->dev;
struct glint_device *gdev = dev->dev_private;
if (mode == glint_crtc->last_dpms) /* Don't do unnecesary mode changes. */
return;
glint_crtc->last_dpms = mode;
switch (mode) {
case DRM_MODE_DPMS_STANDBY:
case DRM_MODE_DPMS_SUSPEND:
case DRM_MODE_DPMS_OFF:
glint_crtc->enabled = false;
break;
case DRM_MODE_DPMS_ON:
glint_crtc->enabled = true;
glint_crtc_load_lut(crtc);
break;
}
}
static bool glint_crtc_mode_fixup(struct drm_crtc *crtc,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
return true;
}
static int glint_crtc_mode_set(struct drm_crtc *crtc,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode,
int x, int y, struct drm_framebuffer *old_fb)
{
/*
struct glint_crtc *glint_crtc = to_glint_crtc(crtc);
glint_crtc_set_base(crtc, x, y, old_fb);
glint_set_crtc_timing(crtc, adjusted_mode);
glint_set_pll(crtc, adjusted_mode);
*/
return 0;
}
static void glint_crtc_prepare(struct drm_crtc *crtc)
{
struct drm_device *dev = crtc->dev;
struct drm_crtc *crtci;
list_for_each_entry(crtci, &dev->mode_config.crtc_list, head)
glint_crtc_dpms(crtci, DRM_MODE_DPMS_OFF);
}
static void glint_crtc_commit(struct drm_crtc *crtc)
{
struct drm_device *dev = crtc->dev;
struct drm_crtc *crtci;
list_for_each_entry(crtci, &dev->mode_config.crtc_list, head) {
if (crtci->enabled)
glint_crtc_dpms(crtci, DRM_MODE_DPMS_ON);
}
}
static void glint_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
u16 *blue, uint32_t size)
{
struct glint_crtc *glint_crtc = to_glint_crtc(crtc);
int i;
if (size != 256) {
return;
}
for (i = 0; i < 256; i++) {
glint_crtc->lut_r[i] = red[i];
glint_crtc->lut_g[i] = green[i];
glint_crtc->lut_b[i] = blue[i];
}
glint_crtc_load_lut(crtc);
}
static void glint_crtc_destroy(struct drm_crtc *crtc)
{
struct glint_crtc *glint_crtc = to_glint_crtc(crtc);
drm_crtc_cleanup(crtc);
kfree(glint_crtc);
}
static const struct drm_crtc_funcs glint_crtc_funcs = {
/*
.cursor_set = glint_crtc_cursor_set,
.cursor_move = glint_crtc_cursor_move,
*/
.cursor_set = NULL,
.cursor_move = NULL,
.gamma_set = glint_crtc_gamma_set,
.set_config = drm_crtc_helper_set_config,
.destroy = glint_crtc_destroy,
};
static const struct drm_crtc_helper_funcs glint_helper_funcs = {
.dpms = glint_crtc_dpms,
.mode_fixup = glint_crtc_mode_fixup,
.mode_set = glint_crtc_mode_set,
/*
.mode_set_base = glint_crtc_set_base,
*/
.prepare = glint_crtc_prepare,
.commit = glint_crtc_commit,
.load_lut = glint_crtc_load_lut,
};
void glint_crtc_init(struct drm_device *dev, int index)
{
struct glint_device *gdev = dev->dev_private;
struct glint_crtc *glint_crtc;
int i;
glint_crtc = kzalloc(sizeof(struct glint_crtc) + (GLINTFB_CONN_LIMIT * sizeof(struct drm_connector *)), GFP_KERNEL);
if (glint_crtc == NULL)
return;
drm_crtc_init(dev, &glint_crtc->base, &glint_crtc_funcs);
drm_mode_crtc_set_gamma_size(&glint_crtc->base, 256);
glint_crtc->crtc_id = index;
glint_crtc->last_dpms = GLINT_DPMS_CLEARED;
gdev->mode_info.crtcs[index] = glint_crtc;
for (i = 0; i < 256; i++) {
glint_crtc->lut_r[i] = i;
glint_crtc->lut_g[i] = i;
glint_crtc->lut_b[i] = i;
}
drm_crtc_helper_add(&glint_crtc->base, &glint_helper_funcs);
}