| #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); |
| } |