sh_mobile_lcdcfb.c revision 0707330b337cec85d7b393303e82f0fad5dc4c00
1cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm/* 2cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm * SuperH Mobile LCDC Framebuffer 3cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm * 4cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm * Copyright (c) 2008 Magnus Damm 5cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm * 6cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm * This file is subject to the terms and conditions of the GNU General Public 7cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm * License. See the file "COPYING" in the main directory of this archive 8cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm * for more details. 9cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm */ 10cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 11f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart#include <linux/atomic.h> 12f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart#include <linux/backlight.h> 13cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm#include <linux/clk.h> 14f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart#include <linux/console.h> 15c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#include <linux/ctype.h> 16cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm#include <linux/dma-mapping.h> 17f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart#include <linux/delay.h> 18f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart#include <linux/gpio.h> 19f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart#include <linux/init.h> 208564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm#include <linux/interrupt.h> 2140331b21f5fdb746e80fc609ef60ef71b5cd47d9Phil Edworthy#include <linux/ioctl.h> 22f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart#include <linux/kernel.h> 23f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart#include <linux/mm.h> 24355b200bacdb6017669cdc5bc9e7b1037aac42a2Paul Gortmaker#include <linux/module.h> 25f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart#include <linux/platform_device.h> 26f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart#include <linux/pm_runtime.h> 27f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart#include <linux/slab.h> 28f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart#include <linux/videodev2.h> 29f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart#include <linux/vmalloc.h> 30f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 31225c9a8d1da274bf23efec43ec28b1c9e45e12f8Paul Mundt#include <video/sh_mobile_lcdc.h> 328a20974f0370fe1b924704399e7ba327d894ef72Laurent Pinchart#include <video/sh_mobile_meram.h> 33cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 346de9edd5bde0cdfea12e9948690e53ec669c3018Guennadi Liakhovetski#include "sh_mobile_lcdcfb.h" 356de9edd5bde0cdfea12e9948690e53ec669c3018Guennadi Liakhovetski 36c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart/* ---------------------------------------------------------------------------- 37c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * Overlay register definitions 38c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart */ 39c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 40c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBCR 0xb00 41c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBCR_UPC(n) (1 << ((n) + 16)) 42c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBCR_UPF(n) (1 << ((n) + 8)) 43c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBCR_UPD(n) (1 << ((n) + 0)) 44c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBnBSIFR(n) (0xb20 + (n) * 0x20 + 0x00) 45c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_EN (1 << 31) 46c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_VS (1 << 29) 47c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_BRSEL (1 << 28) 48c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_MX (1 << 27) 49c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_MY (1 << 26) 50c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_CV3 (3 << 24) 51c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_CV2 (2 << 24) 52c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_CV1 (1 << 24) 53c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_CV0 (0 << 24) 54c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_CV_MASK (3 << 24) 55c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_LAY_MASK (0xff << 16) 56c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_LAY_SHIFT 16 57c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_ROP3_MASK (0xff << 16) 58c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_ROP3_SHIFT 16 59c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_AL_PL8 (3 << 14) 60c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_AL_PL1 (2 << 14) 61c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_AL_PK (1 << 14) 62c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_AL_1 (0 << 14) 63c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_AL_MASK (3 << 14) 64c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_SWPL (1 << 10) 65c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_SWPW (1 << 9) 66c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_SWPB (1 << 8) 67c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_RY (1 << 7) 68c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_CHRR_420 (2 << 0) 69c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_CHRR_422 (1 << 0) 70c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_CHRR_444 (0 << 0) 71c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_RPKF_ARGB32 (0x00 << 0) 72c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_RPKF_RGB16 (0x03 << 0) 73c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_RPKF_RGB24 (0x0b << 0) 74c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSIFR_RPKF_MASK (0x1f << 0) 75c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBnBSSZR(n) (0xb20 + (n) * 0x20 + 0x04) 76c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSSZR_BVSS_MASK (0xfff << 16) 77c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSSZR_BVSS_SHIFT 16 78c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSSZR_BHSS_MASK (0xfff << 0) 79c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSSZR_BHSS_SHIFT 0 80c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBnBLOCR(n) (0xb20 + (n) * 0x20 + 0x08) 81c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBLOCR_CVLC_MASK (0xfff << 16) 82c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBLOCR_CVLC_SHIFT 16 83c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBLOCR_CHLC_MASK (0xfff << 0) 84c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBLOCR_CHLC_SHIFT 0 85c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBnBSMWR(n) (0xb20 + (n) * 0x20 + 0x0c) 86c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSMWR_BSMWA_MASK (0xffff << 16) 87c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSMWR_BSMWA_SHIFT 16 88c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSMWR_BSMW_MASK (0xffff << 0) 89c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSMWR_BSMW_SHIFT 0 90c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBnBSAYR(n) (0xb20 + (n) * 0x20 + 0x10) 91c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSAYR_FG1A_MASK (0xff << 24) 92c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSAYR_FG1A_SHIFT 24 93c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSAYR_FG1R_MASK (0xff << 16) 94c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSAYR_FG1R_SHIFT 16 95c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSAYR_FG1G_MASK (0xff << 8) 96c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSAYR_FG1G_SHIFT 8 97c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSAYR_FG1B_MASK (0xff << 0) 98c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSAYR_FG1B_SHIFT 0 99c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBnBSACR(n) (0xb20 + (n) * 0x20 + 0x14) 100c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSACR_FG2A_MASK (0xff << 24) 101c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSACR_FG2A_SHIFT 24 102c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSACR_FG2R_MASK (0xff << 16) 103c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSACR_FG2R_SHIFT 16 104c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSACR_FG2G_MASK (0xff << 8) 105c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSACR_FG2G_SHIFT 8 106c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSACR_FG2B_MASK (0xff << 0) 107c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSACR_FG2B_SHIFT 0 108c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBnBSAAR(n) (0xb20 + (n) * 0x20 + 0x18) 109c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSAAR_AP_MASK (0xff << 24) 110c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSAAR_AP_SHIFT 24 111c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSAAR_R_MASK (0xff << 16) 112c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSAAR_R_SHIFT 16 113c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSAAR_GY_MASK (0xff << 8) 114c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSAAR_GY_SHIFT 8 115c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSAAR_B_MASK (0xff << 0) 116c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBSAAR_B_SHIFT 0 117c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBnBPPCR(n) (0xb20 + (n) * 0x20 + 0x1c) 118c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBPPCR_AP_MASK (0xff << 24) 119c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBPPCR_AP_SHIFT 24 120c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBPPCR_R_MASK (0xff << 16) 121c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBPPCR_R_SHIFT 16 122c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBPPCR_GY_MASK (0xff << 8) 123c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBPPCR_GY_SHIFT 8 124c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBPPCR_B_MASK (0xff << 0) 125c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBPPCR_B_SHIFT 0 126c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBnBBGCL(n) (0xb10 + (n) * 0x04) 127c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBBGCL_BGA_MASK (0xff << 24) 128c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBBGCL_BGA_SHIFT 24 129c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBBGCL_BGR_MASK (0xff << 16) 130c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBBGCL_BGR_SHIFT 16 131c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBBGCL_BGG_MASK (0xff << 8) 132c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBBGCL_BGG_SHIFT 8 133c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBBGCL_BGB_MASK (0xff << 0) 134c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart#define LDBBBGCL_BGB_SHIFT 0 135c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 136a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy#define SIDE_B_OFFSET 0x1000 137a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy#define MIRROR_OFFSET 0x2000 138cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 139d2ecbab5960d9814a269d36723647d6ef391ba8fGuennadi Liakhovetski#define MAX_XRES 1920 140d2ecbab5960d9814a269d36723647d6ef391ba8fGuennadi Liakhovetski#define MAX_YRES 1080 141cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 142c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartenum sh_mobile_lcdc_overlay_mode { 143c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart LCDC_OVERLAY_BLEND, 144c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart LCDC_OVERLAY_ROP3, 145c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart}; 146c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 147c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart/* 148c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * struct sh_mobile_lcdc_overlay - LCDC display overlay 149c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * 150c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * @channel: LCDC channel this overlay belongs to 151c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * @cfg: Overlay configuration 152c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * @info: Frame buffer device 153c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * @index: Overlay index (0-3) 154c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * @base: Overlay registers base address 155c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * @enabled: True if the overlay is enabled 156c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * @mode: Overlay blending mode (alpha blend or ROP3) 157c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * @alpha: Global alpha blending value (0-255, for alpha blending mode) 158c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * @rop3: Raster operation (for ROP3 mode) 159c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * @fb_mem: Frame buffer virtual memory address 160c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * @fb_size: Frame buffer size in bytes 161c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * @dma_handle: Frame buffer DMA address 162c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * @base_addr_y: Overlay base address (RGB or luma component) 163c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * @base_addr_c: Overlay base address (chroma component) 164a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart * @pan_y_offset: Panning linear offset in bytes (luma component) 165c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * @format: Current pixelf format 166c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * @xres: Horizontal visible resolution 167c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * @xres_virtual: Horizontal total resolution 168c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * @yres: Vertical visible resolution 169c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * @yres_virtual: Vertical total resolution 170c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * @pitch: Overlay line pitch 171c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * @pos_x: Horizontal overlay position 172c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * @pos_y: Vertical overlay position 173c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart */ 174c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstruct sh_mobile_lcdc_overlay { 175c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_chan *channel; 176c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 177c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart const struct sh_mobile_lcdc_overlay_cfg *cfg; 178c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct fb_info *info; 179c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 180c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart unsigned int index; 181c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart unsigned long base; 182c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 183c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart bool enabled; 184c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart enum sh_mobile_lcdc_overlay_mode mode; 185c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart unsigned int alpha; 186c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart unsigned int rop3; 187c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 188c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart void *fb_mem; 189c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart unsigned long fb_size; 190c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 191c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart dma_addr_t dma_handle; 192c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart unsigned long base_addr_y; 193c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart unsigned long base_addr_c; 194a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart unsigned long pan_y_offset; 195c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 196c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart const struct sh_mobile_lcdc_format_info *format; 197c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart unsigned int xres; 198c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart unsigned int xres_virtual; 199c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart unsigned int yres; 200c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart unsigned int yres_virtual; 201c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart unsigned int pitch; 202c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart int pos_x; 203c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart int pos_y; 204c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart}; 205c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 206f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchartstruct sh_mobile_lcdc_priv { 207f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart void __iomem *base; 208f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart int irq; 209f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart atomic_t hw_usecnt; 210f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart struct device *dev; 211f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart struct clk *dot_clk; 212f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart unsigned long lddckr; 213c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 214f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart struct sh_mobile_lcdc_chan ch[2]; 215c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_overlay overlays[4]; 216c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 217f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart struct notifier_block notifier; 218f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart int started; 219f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart int forced_fourcc; /* 2 channel LCDC must share fourcc setting */ 220f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart struct sh_mobile_meram_info *meram_dev; 221f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart}; 222f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 223f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart/* ----------------------------------------------------------------------------- 224f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart * Registers access 225f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart */ 226f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 2270246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Dammstatic unsigned long lcdc_offs_mainlcd[NR_CH_REGS] = { 228cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm [LDDCKPAT1R] = 0x400, 229cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm [LDDCKPAT2R] = 0x404, 230cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm [LDMT1R] = 0x418, 231cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm [LDMT2R] = 0x41c, 232cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm [LDMT3R] = 0x420, 233cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm [LDDFR] = 0x424, 234cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm [LDSM1R] = 0x428, 2358564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm [LDSM2R] = 0x42c, 236cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm [LDSA1R] = 0x430, 23753b5031430bb3a7941b340b453afe4eabeb5340cDamian Hobson-Garcia [LDSA2R] = 0x434, 238cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm [LDMLSR] = 0x438, 239cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm [LDHCNR] = 0x448, 240cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm [LDHSYNR] = 0x44c, 241cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm [LDVLNR] = 0x450, 242cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm [LDVSYNR] = 0x454, 243cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm [LDPMR] = 0x460, 2446011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski [LDHAJR] = 0x4a0, 245cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm}; 246cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 2470246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Dammstatic unsigned long lcdc_offs_sublcd[NR_CH_REGS] = { 248cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm [LDDCKPAT1R] = 0x408, 249cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm [LDDCKPAT2R] = 0x40c, 250cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm [LDMT1R] = 0x600, 251cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm [LDMT2R] = 0x604, 252cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm [LDMT3R] = 0x608, 253cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm [LDDFR] = 0x60c, 254cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm [LDSM1R] = 0x610, 2558564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm [LDSM2R] = 0x614, 256cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm [LDSA1R] = 0x618, 257cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm [LDMLSR] = 0x620, 258cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm [LDHCNR] = 0x624, 259cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm [LDHSYNR] = 0x628, 260cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm [LDVLNR] = 0x62c, 261cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm [LDVSYNR] = 0x630, 262cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm [LDPMR] = 0x63c, 263cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm}; 264cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 265a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthystatic bool banked(int reg_nr) 266a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy{ 267a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy switch (reg_nr) { 268a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy case LDMT1R: 269a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy case LDMT2R: 270a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy case LDMT3R: 271a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy case LDDFR: 272a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy case LDSM1R: 273a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy case LDSA1R: 27453b5031430bb3a7941b340b453afe4eabeb5340cDamian Hobson-Garcia case LDSA2R: 275a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy case LDMLSR: 276a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy case LDHCNR: 277a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy case LDHSYNR: 278a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy case LDVLNR: 279a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy case LDVSYNR: 280a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy return true; 281a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy } 282a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy return false; 283a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy} 284a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy 285f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchartstatic int lcdc_chan_is_sublcd(struct sh_mobile_lcdc_chan *chan) 286f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart{ 287b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart return chan->cfg->chan == LCDC_CHAN_SUBLCD; 288f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart} 289f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 290cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Dammstatic void lcdc_write_chan(struct sh_mobile_lcdc_chan *chan, 291cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm int reg_nr, unsigned long data) 292cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm{ 293cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm iowrite32(data, chan->lcdc->base + chan->reg_offs[reg_nr]); 294a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy if (banked(reg_nr)) 295a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy iowrite32(data, chan->lcdc->base + chan->reg_offs[reg_nr] + 296a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy SIDE_B_OFFSET); 297a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy} 298a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy 299a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthystatic void lcdc_write_chan_mirror(struct sh_mobile_lcdc_chan *chan, 300a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy int reg_nr, unsigned long data) 301a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy{ 302a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy iowrite32(data, chan->lcdc->base + chan->reg_offs[reg_nr] + 303a6f15ade97989d414e9bf33874c9d5d1f39808ecPhil Edworthy MIRROR_OFFSET); 304cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm} 305cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 306cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Dammstatic unsigned long lcdc_read_chan(struct sh_mobile_lcdc_chan *chan, 307cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm int reg_nr) 308cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm{ 309cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm return ioread32(chan->lcdc->base + chan->reg_offs[reg_nr]); 310cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm} 311cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 312c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic void lcdc_write_overlay(struct sh_mobile_lcdc_overlay *ovl, 313c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart int reg, unsigned long data) 314c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 315c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart iowrite32(data, ovl->channel->lcdc->base + reg); 316c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart iowrite32(data, ovl->channel->lcdc->base + reg + SIDE_B_OFFSET); 317c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 318c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 319cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Dammstatic void lcdc_write(struct sh_mobile_lcdc_priv *priv, 320cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm unsigned long reg_offs, unsigned long data) 321cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm{ 322cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm iowrite32(data, priv->base + reg_offs); 323cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm} 324cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 325cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Dammstatic unsigned long lcdc_read(struct sh_mobile_lcdc_priv *priv, 326cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm unsigned long reg_offs) 327cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm{ 328cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm return ioread32(priv->base + reg_offs); 329cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm} 330cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 331cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Dammstatic void lcdc_wait_bit(struct sh_mobile_lcdc_priv *priv, 332cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm unsigned long reg_offs, 333cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm unsigned long mask, unsigned long until) 334cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm{ 335cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm while ((lcdc_read(priv, reg_offs) & mask) != until) 336cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm cpu_relax(); 337cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm} 338cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 339f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart/* ----------------------------------------------------------------------------- 340f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart * Clock management 341f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart */ 342f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 343f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchartstatic void sh_mobile_lcdc_clk_on(struct sh_mobile_lcdc_priv *priv) 344cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm{ 345f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart if (atomic_inc_and_test(&priv->hw_usecnt)) { 346f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart if (priv->dot_clk) 347f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart clk_enable(priv->dot_clk); 348f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart pm_runtime_get_sync(priv->dev); 349f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart if (priv->meram_dev && priv->meram_dev->pdev) 350f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart pm_runtime_get_sync(&priv->meram_dev->pdev->dev); 351f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart } 352cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm} 353cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 354f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchartstatic void sh_mobile_lcdc_clk_off(struct sh_mobile_lcdc_priv *priv) 355f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart{ 356f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart if (atomic_sub_return(1, &priv->hw_usecnt) == -1) { 357f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart if (priv->meram_dev && priv->meram_dev->pdev) 358f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart pm_runtime_put_sync(&priv->meram_dev->pdev->dev); 359f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart pm_runtime_put(priv->dev); 360f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart if (priv->dot_clk) 361f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart clk_disable(priv->dot_clk); 362f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart } 363f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart} 364f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 3650a7f17aa3d6b693700af2e1cbf8cfdd28e18aebbLaurent Pinchartstatic int sh_mobile_lcdc_setup_clocks(struct sh_mobile_lcdc_priv *priv, 3660a7f17aa3d6b693700af2e1cbf8cfdd28e18aebbLaurent Pinchart int clock_source) 367f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart{ 3684774c12aacafc0b8be81b1d159be5a761889e2d7Laurent Pinchart struct clk *clk; 369f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart char *str; 370f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 371f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart switch (clock_source) { 372f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case LCDC_CLK_BUS: 373f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart str = "bus_clk"; 374f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart priv->lddckr = LDDCKR_ICKSEL_BUS; 375f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart break; 376f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case LCDC_CLK_PERIPHERAL: 377f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart str = "peripheral_clk"; 378f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart priv->lddckr = LDDCKR_ICKSEL_MIPI; 379f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart break; 380f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case LCDC_CLK_EXTERNAL: 381f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart str = NULL; 382f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart priv->lddckr = LDDCKR_ICKSEL_HDMI; 383f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart break; 384f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart default: 385f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart return -EINVAL; 386f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart } 387f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 3884774c12aacafc0b8be81b1d159be5a761889e2d7Laurent Pinchart if (str == NULL) 3894774c12aacafc0b8be81b1d159be5a761889e2d7Laurent Pinchart return 0; 3904774c12aacafc0b8be81b1d159be5a761889e2d7Laurent Pinchart 3910a7f17aa3d6b693700af2e1cbf8cfdd28e18aebbLaurent Pinchart clk = clk_get(priv->dev, str); 3924774c12aacafc0b8be81b1d159be5a761889e2d7Laurent Pinchart if (IS_ERR(clk)) { 3930a7f17aa3d6b693700af2e1cbf8cfdd28e18aebbLaurent Pinchart dev_err(priv->dev, "cannot get dot clock %s\n", str); 3944774c12aacafc0b8be81b1d159be5a761889e2d7Laurent Pinchart return PTR_ERR(clk); 395f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart } 396f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 3974774c12aacafc0b8be81b1d159be5a761889e2d7Laurent Pinchart priv->dot_clk = clk; 398f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart return 0; 399f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart} 400f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 401f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart/* ----------------------------------------------------------------------------- 40237c5dcc21ddaa9f946c4d691996bb3076598b813Laurent Pinchart * Display, panel and deferred I/O 403f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart */ 404f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 405cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Dammstatic void lcdc_sys_write_index(void *handle, unsigned long data) 406cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm{ 407cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm struct sh_mobile_lcdc_chan *ch = handle; 408cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 409ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart lcdc_write(ch->lcdc, _LDDWD0R, data | LDDWDxR_WDACT); 410ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0); 411ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart lcdc_write(ch->lcdc, _LDDWAR, LDDWAR_WA | 412ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart (lcdc_chan_is_sublcd(ch) ? 2 : 0)); 413ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0); 414cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm} 415cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 416cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Dammstatic void lcdc_sys_write_data(void *handle, unsigned long data) 417cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm{ 418cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm struct sh_mobile_lcdc_chan *ch = handle; 419cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 420ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart lcdc_write(ch->lcdc, _LDDWD0R, data | LDDWDxR_WDACT | LDDWDxR_RSW); 421ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0); 422ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart lcdc_write(ch->lcdc, _LDDWAR, LDDWAR_WA | 423ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart (lcdc_chan_is_sublcd(ch) ? 2 : 0)); 424ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0); 425cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm} 426cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 427cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Dammstatic unsigned long lcdc_sys_read_data(void *handle) 428cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm{ 429cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm struct sh_mobile_lcdc_chan *ch = handle; 430cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 431ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart lcdc_write(ch->lcdc, _LDDRDR, LDDRDR_RSR); 432ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0); 433ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart lcdc_write(ch->lcdc, _LDDRAR, LDDRAR_RA | 434ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart (lcdc_chan_is_sublcd(ch) ? 2 : 0)); 435cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm udelay(1); 436ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart lcdc_wait_bit(ch->lcdc, _LDSR, LDSR_AS, 0); 437cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 438ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart return lcdc_read(ch->lcdc, _LDDRDR) & LDDRDR_DRD_MASK; 439cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm} 440cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 441cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Dammstruct sh_mobile_lcdc_sys_bus_ops sh_mobile_lcdc_sys_bus_ops = { 442cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm lcdc_sys_write_index, 443cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm lcdc_sys_write_data, 444cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm lcdc_sys_read_data, 445cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm}; 446cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 4471c6a307a54668eda556f499c94e75086aaf8f80fPaul Mundtstatic int sh_mobile_lcdc_sginit(struct fb_info *info, 4481c6a307a54668eda556f499c94e75086aaf8f80fPaul Mundt struct list_head *pagelist) 4491c6a307a54668eda556f499c94e75086aaf8f80fPaul Mundt{ 4501c6a307a54668eda556f499c94e75086aaf8f80fPaul Mundt struct sh_mobile_lcdc_chan *ch = info->par; 45158f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart unsigned int nr_pages_max = ch->fb_size >> PAGE_SHIFT; 4521c6a307a54668eda556f499c94e75086aaf8f80fPaul Mundt struct page *page; 4531c6a307a54668eda556f499c94e75086aaf8f80fPaul Mundt int nr_pages = 0; 4541c6a307a54668eda556f499c94e75086aaf8f80fPaul Mundt 4551c6a307a54668eda556f499c94e75086aaf8f80fPaul Mundt sg_init_table(ch->sglist, nr_pages_max); 4561c6a307a54668eda556f499c94e75086aaf8f80fPaul Mundt 4571c6a307a54668eda556f499c94e75086aaf8f80fPaul Mundt list_for_each_entry(page, pagelist, lru) 4581c6a307a54668eda556f499c94e75086aaf8f80fPaul Mundt sg_set_page(&ch->sglist[nr_pages++], page, PAGE_SIZE, 0); 4591c6a307a54668eda556f499c94e75086aaf8f80fPaul Mundt 4601c6a307a54668eda556f499c94e75086aaf8f80fPaul Mundt return nr_pages; 4611c6a307a54668eda556f499c94e75086aaf8f80fPaul Mundt} 4621c6a307a54668eda556f499c94e75086aaf8f80fPaul Mundt 4638564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Dammstatic void sh_mobile_lcdc_deferred_io(struct fb_info *info, 4648564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm struct list_head *pagelist) 4658564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm{ 4668564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm struct sh_mobile_lcdc_chan *ch = info->par; 467b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart const struct sh_mobile_lcdc_panel_cfg *panel = &ch->cfg->panel_cfg; 4688564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm 4698564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm /* enable clocks before accessing hardware */ 4708564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm sh_mobile_lcdc_clk_on(ch->lcdc); 4718564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm 4725c1a56b5f616f7063f91eb85f0ea209658f387dcPaul Mundt /* 4735c1a56b5f616f7063f91eb85f0ea209658f387dcPaul Mundt * It's possible to get here without anything on the pagelist via 4745c1a56b5f616f7063f91eb85f0ea209658f387dcPaul Mundt * sh_mobile_lcdc_deferred_io_touch() or via a userspace fsync() 4755c1a56b5f616f7063f91eb85f0ea209658f387dcPaul Mundt * invocation. In the former case, the acceleration routines are 4765c1a56b5f616f7063f91eb85f0ea209658f387dcPaul Mundt * stepped in to when using the framebuffer console causing the 4775c1a56b5f616f7063f91eb85f0ea209658f387dcPaul Mundt * workqueue to be scheduled without any dirty pages on the list. 4785c1a56b5f616f7063f91eb85f0ea209658f387dcPaul Mundt * 4795c1a56b5f616f7063f91eb85f0ea209658f387dcPaul Mundt * Despite this, a panel update is still needed given that the 4805c1a56b5f616f7063f91eb85f0ea209658f387dcPaul Mundt * acceleration routines have their own methods for writing in 4815c1a56b5f616f7063f91eb85f0ea209658f387dcPaul Mundt * that still need to be updated. 4825c1a56b5f616f7063f91eb85f0ea209658f387dcPaul Mundt * 4835c1a56b5f616f7063f91eb85f0ea209658f387dcPaul Mundt * The fsync() and empty pagelist case could be optimized for, 4845c1a56b5f616f7063f91eb85f0ea209658f387dcPaul Mundt * but we don't bother, as any application exhibiting such 4855c1a56b5f616f7063f91eb85f0ea209658f387dcPaul Mundt * behaviour is fundamentally broken anyways. 4865c1a56b5f616f7063f91eb85f0ea209658f387dcPaul Mundt */ 4875c1a56b5f616f7063f91eb85f0ea209658f387dcPaul Mundt if (!list_empty(pagelist)) { 4885c1a56b5f616f7063f91eb85f0ea209658f387dcPaul Mundt unsigned int nr_pages = sh_mobile_lcdc_sginit(info, pagelist); 4895c1a56b5f616f7063f91eb85f0ea209658f387dcPaul Mundt 4905c1a56b5f616f7063f91eb85f0ea209658f387dcPaul Mundt /* trigger panel update */ 491e8363140c02c92c122210e03103aef72dd836664Laurent Pinchart dma_map_sg(ch->lcdc->dev, ch->sglist, nr_pages, DMA_TO_DEVICE); 492afaad83b9c0d24eac88535cc5a8c6019f0c45bcbLaurent Pinchart if (panel->start_transfer) 493afaad83b9c0d24eac88535cc5a8c6019f0c45bcbLaurent Pinchart panel->start_transfer(ch, &sh_mobile_lcdc_sys_bus_ops); 494ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart lcdc_write_chan(ch, LDSM2R, LDSM2R_OSTRG); 495e8363140c02c92c122210e03103aef72dd836664Laurent Pinchart dma_unmap_sg(ch->lcdc->dev, ch->sglist, nr_pages, 496e8363140c02c92c122210e03103aef72dd836664Laurent Pinchart DMA_TO_DEVICE); 497ef61aae4ddf1dbd0e9b6ad21e2e57632a8fe76f6Magnus Damm } else { 498afaad83b9c0d24eac88535cc5a8c6019f0c45bcbLaurent Pinchart if (panel->start_transfer) 499afaad83b9c0d24eac88535cc5a8c6019f0c45bcbLaurent Pinchart panel->start_transfer(ch, &sh_mobile_lcdc_sys_bus_ops); 500ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart lcdc_write_chan(ch, LDSM2R, LDSM2R_OSTRG); 501ef61aae4ddf1dbd0e9b6ad21e2e57632a8fe76f6Magnus Damm } 5028564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm} 5038564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm 5048564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Dammstatic void sh_mobile_lcdc_deferred_io_touch(struct fb_info *info) 5058564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm{ 5068564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm struct fb_deferred_io *fbdefio = info->fbdefio; 5078564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm 5088564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm if (fbdefio) 5098564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm schedule_delayed_work(&info->deferred_work, fbdefio->delay); 5108564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm} 5118564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm 51237c5dcc21ddaa9f946c4d691996bb3076598b813Laurent Pinchartstatic void sh_mobile_lcdc_display_on(struct sh_mobile_lcdc_chan *ch) 51337c5dcc21ddaa9f946c4d691996bb3076598b813Laurent Pinchart{ 514b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart const struct sh_mobile_lcdc_panel_cfg *panel = &ch->cfg->panel_cfg; 51537c5dcc21ddaa9f946c4d691996bb3076598b813Laurent Pinchart 5169a2985e7f943678154f5761dad753f1987c2fdd0Laurent Pinchart if (ch->tx_dev) { 517458981c3886133667e020900f53538f1fbc3ea1dLaurent Pinchart int ret; 518458981c3886133667e020900f53538f1fbc3ea1dLaurent Pinchart 519458981c3886133667e020900f53538f1fbc3ea1dLaurent Pinchart ret = ch->tx_dev->ops->display_on(ch->tx_dev); 520458981c3886133667e020900f53538f1fbc3ea1dLaurent Pinchart if (ret < 0) 5219a2985e7f943678154f5761dad753f1987c2fdd0Laurent Pinchart return; 522458981c3886133667e020900f53538f1fbc3ea1dLaurent Pinchart 523458981c3886133667e020900f53538f1fbc3ea1dLaurent Pinchart if (ret == SH_MOBILE_LCDC_DISPLAY_DISCONNECTED) 524458981c3886133667e020900f53538f1fbc3ea1dLaurent Pinchart ch->info->state = FBINFO_STATE_SUSPENDED; 5259a2985e7f943678154f5761dad753f1987c2fdd0Laurent Pinchart } 5269a2985e7f943678154f5761dad753f1987c2fdd0Laurent Pinchart 52737c5dcc21ddaa9f946c4d691996bb3076598b813Laurent Pinchart /* HDMI must be enabled before LCDC configuration */ 528afaad83b9c0d24eac88535cc5a8c6019f0c45bcbLaurent Pinchart if (panel->display_on) 529afaad83b9c0d24eac88535cc5a8c6019f0c45bcbLaurent Pinchart panel->display_on(); 53037c5dcc21ddaa9f946c4d691996bb3076598b813Laurent Pinchart} 53137c5dcc21ddaa9f946c4d691996bb3076598b813Laurent Pinchart 53237c5dcc21ddaa9f946c4d691996bb3076598b813Laurent Pinchartstatic void sh_mobile_lcdc_display_off(struct sh_mobile_lcdc_chan *ch) 53337c5dcc21ddaa9f946c4d691996bb3076598b813Laurent Pinchart{ 534b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart const struct sh_mobile_lcdc_panel_cfg *panel = &ch->cfg->panel_cfg; 53537c5dcc21ddaa9f946c4d691996bb3076598b813Laurent Pinchart 536afaad83b9c0d24eac88535cc5a8c6019f0c45bcbLaurent Pinchart if (panel->display_off) 537afaad83b9c0d24eac88535cc5a8c6019f0c45bcbLaurent Pinchart panel->display_off(); 5389a2985e7f943678154f5761dad753f1987c2fdd0Laurent Pinchart 5399a2985e7f943678154f5761dad753f1987c2fdd0Laurent Pinchart if (ch->tx_dev) 5409a2985e7f943678154f5761dad753f1987c2fdd0Laurent Pinchart ch->tx_dev->ops->display_off(ch->tx_dev); 54137c5dcc21ddaa9f946c4d691996bb3076598b813Laurent Pinchart} 54237c5dcc21ddaa9f946c4d691996bb3076598b813Laurent Pinchart 543ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchartstatic bool 544ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchartsh_mobile_lcdc_must_reconfigure(struct sh_mobile_lcdc_chan *ch, 545e0c8601a18969229eb63065e5c3176319c785288Laurent Pinchart const struct fb_videomode *new_mode) 546ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart{ 547ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart dev_dbg(ch->info->dev, "Old %ux%u, new %ux%u\n", 5482d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart ch->display.mode.xres, ch->display.mode.yres, 5492d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart new_mode->xres, new_mode->yres); 550ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart 551e0c8601a18969229eb63065e5c3176319c785288Laurent Pinchart /* It can be a different monitor with an equal video-mode */ 5522d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart if (fb_mode_is_equal(&ch->display.mode, new_mode)) 553ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart return false; 554ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart 555ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart dev_dbg(ch->info->dev, "Switching %u -> %u lines\n", 5562d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart ch->display.mode.yres, new_mode->yres); 5572d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart ch->display.mode = *new_mode; 558ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart 559ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart return true; 560ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart} 561ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart 562d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchartstatic int sh_mobile_lcdc_check_var(struct fb_var_screeninfo *var, 563d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchart struct fb_info *info); 564ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart 565ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchartstatic int sh_mobile_lcdc_display_notify(struct sh_mobile_lcdc_chan *ch, 566ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart enum sh_mobile_lcdc_entity_event event, 567e0c8601a18969229eb63065e5c3176319c785288Laurent Pinchart const struct fb_videomode *mode, 568e0c8601a18969229eb63065e5c3176319c785288Laurent Pinchart const struct fb_monspecs *monspec) 569ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart{ 570ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart struct fb_info *info = ch->info; 571e0c8601a18969229eb63065e5c3176319c785288Laurent Pinchart struct fb_var_screeninfo var; 572ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart int ret = 0; 573ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart 574ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart switch (event) { 575ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart case SH_MOBILE_LCDC_EVENT_DISPLAY_CONNECT: 576ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart /* HDMI plug in */ 577ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart if (lock_fb_info(info)) { 578ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart console_lock(); 579ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart 5802d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart ch->display.width = monspec->max_x * 10; 5812d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart ch->display.height = monspec->max_y * 10; 582e0c8601a18969229eb63065e5c3176319c785288Laurent Pinchart 583e0c8601a18969229eb63065e5c3176319c785288Laurent Pinchart if (!sh_mobile_lcdc_must_reconfigure(ch, mode) && 584ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart info->state == FBINFO_STATE_RUNNING) { 585ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart /* First activation with the default monitor. 586ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart * Just turn on, if we run a resume here, the 587ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart * logo disappears. 588ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart */ 589856e8dfe6efed7cf35bc6bf827f030a164bee083Laurent Pinchart info->var.width = ch->display.width; 590856e8dfe6efed7cf35bc6bf827f030a164bee083Laurent Pinchart info->var.height = ch->display.height; 591ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart sh_mobile_lcdc_display_on(ch); 592ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart } else { 593ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart /* New monitor or have to wake up */ 594ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart fb_set_suspend(info, 0); 595ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart } 596ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart 597ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart console_unlock(); 598ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart unlock_fb_info(info); 599ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart } 600ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart break; 601ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart 602ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart case SH_MOBILE_LCDC_EVENT_DISPLAY_DISCONNECT: 603ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart /* HDMI disconnect */ 604ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart if (lock_fb_info(info)) { 605ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart console_lock(); 606ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart fb_set_suspend(info, 1); 607ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart console_unlock(); 608ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart unlock_fb_info(info); 609ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart } 610ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart break; 611ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart 612ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart case SH_MOBILE_LCDC_EVENT_DISPLAY_MODE: 613ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart /* Validate a proposed new mode */ 614e0c8601a18969229eb63065e5c3176319c785288Laurent Pinchart fb_videomode_to_var(&var, mode); 615e0c8601a18969229eb63065e5c3176319c785288Laurent Pinchart var.bits_per_pixel = info->var.bits_per_pixel; 616e0c8601a18969229eb63065e5c3176319c785288Laurent Pinchart var.grayscale = info->var.grayscale; 617d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchart ret = sh_mobile_lcdc_check_var(&var, info); 618ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart break; 619ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart } 620ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart 621ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart return ret; 622ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart} 623ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart 624f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart/* ----------------------------------------------------------------------------- 625f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart * Format helpers 626f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart */ 627f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 628105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchartstruct sh_mobile_lcdc_format_info { 629105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart u32 fourcc; 630105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart unsigned int bpp; 631105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart bool yuv; 632105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart u32 lddfr; 633105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart}; 634105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart 635105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchartstatic const struct sh_mobile_lcdc_format_info sh_mobile_format_infos[] = { 636105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart { 637105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .fourcc = V4L2_PIX_FMT_RGB565, 638105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .bpp = 16, 639105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .yuv = false, 640105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .lddfr = LDDFR_PKF_RGB16, 641105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart }, { 642105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .fourcc = V4L2_PIX_FMT_BGR24, 643105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .bpp = 24, 644105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .yuv = false, 645105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .lddfr = LDDFR_PKF_RGB24, 646105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart }, { 647105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .fourcc = V4L2_PIX_FMT_BGR32, 648105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .bpp = 32, 649105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .yuv = false, 650105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .lddfr = LDDFR_PKF_ARGB32, 651105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart }, { 652105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .fourcc = V4L2_PIX_FMT_NV12, 653105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .bpp = 12, 654105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .yuv = true, 655105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .lddfr = LDDFR_CC | LDDFR_YF_420, 656105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart }, { 657105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .fourcc = V4L2_PIX_FMT_NV21, 658105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .bpp = 12, 659105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .yuv = true, 660105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .lddfr = LDDFR_CC | LDDFR_YF_420, 661105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart }, { 662105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .fourcc = V4L2_PIX_FMT_NV16, 663105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .bpp = 16, 664105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .yuv = true, 665105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .lddfr = LDDFR_CC | LDDFR_YF_422, 666105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart }, { 667105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .fourcc = V4L2_PIX_FMT_NV61, 668105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .bpp = 16, 669105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .yuv = true, 670105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .lddfr = LDDFR_CC | LDDFR_YF_422, 671105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart }, { 672105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .fourcc = V4L2_PIX_FMT_NV24, 673105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .bpp = 24, 674105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .yuv = true, 675105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .lddfr = LDDFR_CC | LDDFR_YF_444, 676105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart }, { 677105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .fourcc = V4L2_PIX_FMT_NV42, 678105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .bpp = 24, 679105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .yuv = true, 680105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart .lddfr = LDDFR_CC | LDDFR_YF_444, 681105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart }, 682105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart}; 683105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart 684105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchartstatic const struct sh_mobile_lcdc_format_info * 685105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchartsh_mobile_format_info(u32 fourcc) 686105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart{ 687105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart unsigned int i; 688105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart 689105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart for (i = 0; i < ARRAY_SIZE(sh_mobile_format_infos); ++i) { 690105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart if (sh_mobile_format_infos[i].fourcc == fourcc) 691105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart return &sh_mobile_format_infos[i]; 692105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart } 693105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart 694105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart return NULL; 695105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart} 696105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart 697f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchartstatic int sh_mobile_format_fourcc(const struct fb_var_screeninfo *var) 698f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart{ 699f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart if (var->grayscale > 1) 700f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart return var->grayscale; 701f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 702f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart switch (var->bits_per_pixel) { 703f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case 16: 704f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart return V4L2_PIX_FMT_RGB565; 705f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case 24: 706f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart return V4L2_PIX_FMT_BGR24; 707f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case 32: 708f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart return V4L2_PIX_FMT_BGR32; 709f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart default: 710f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart return 0; 711f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart } 712f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart} 713f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 714f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchartstatic int sh_mobile_format_is_fourcc(const struct fb_var_screeninfo *var) 715f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart{ 716f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart return var->grayscale > 1; 717f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart} 718f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 719f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart/* ----------------------------------------------------------------------------- 720f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart * Start, stop and IRQ 721f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart */ 722f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 7238564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Dammstatic irqreturn_t sh_mobile_lcdc_irq(int irq, void *data) 7248564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm{ 7258564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm struct sh_mobile_lcdc_priv *priv = data; 7262feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm struct sh_mobile_lcdc_chan *ch; 7279dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy unsigned long ldintr; 7282feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm int is_sub; 7292feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm int k; 7308564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm 731dc48665fae5aa360e80dfdb2d6cab4fa58b27ee4Laurent Pinchart /* Acknowledge interrupts and disable further VSYNC End IRQs. */ 732dc48665fae5aa360e80dfdb2d6cab4fa58b27ee4Laurent Pinchart ldintr = lcdc_read(priv, _LDINTR); 733dc48665fae5aa360e80dfdb2d6cab4fa58b27ee4Laurent Pinchart lcdc_write(priv, _LDINTR, (ldintr ^ LDINTR_STATUS_MASK) & ~LDINTR_VEE); 7348564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm 7352feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm /* figure out if this interrupt is for main or sub lcd */ 736ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart is_sub = (lcdc_read(priv, _LDSR) & LDSR_MSS) ? 1 : 0; 7372feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm 7389dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy /* wake up channel and disable clocks */ 7392feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { 7402feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm ch = &priv->ch[k]; 7412feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm 7422feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm if (!ch->enabled) 7432feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm continue; 7442feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm 745dc48665fae5aa360e80dfdb2d6cab4fa58b27ee4Laurent Pinchart /* Frame End */ 7469dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy if (ldintr & LDINTR_FS) { 7479dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy if (is_sub == lcdc_chan_is_sublcd(ch)) { 7489dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy ch->frame_end = 1; 7499dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy wake_up(&ch->frame_end_wait); 7502feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm 7519dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy sh_mobile_lcdc_clk_off(priv); 7529dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy } 7539dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy } 7549dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy 7559dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy /* VSYNC End */ 75640331b21f5fdb746e80fc609ef60ef71b5cd47d9Phil Edworthy if (ldintr & LDINTR_VES) 75740331b21f5fdb746e80fc609ef60ef71b5cd47d9Phil Edworthy complete(&ch->vsync_completion); 7582feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm } 7592feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm 7608564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm return IRQ_HANDLED; 7618564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm} 7628564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm 763d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchartstatic int sh_mobile_lcdc_wait_for_vsync(struct sh_mobile_lcdc_chan *ch) 7644976677f4d34df74d7207cae934b27f5d86feaceLaurent Pinchart{ 7654976677f4d34df74d7207cae934b27f5d86feaceLaurent Pinchart unsigned long ldintr; 7664976677f4d34df74d7207cae934b27f5d86feaceLaurent Pinchart int ret; 7674976677f4d34df74d7207cae934b27f5d86feaceLaurent Pinchart 7684976677f4d34df74d7207cae934b27f5d86feaceLaurent Pinchart /* Enable VSync End interrupt and be careful not to acknowledge any 7694976677f4d34df74d7207cae934b27f5d86feaceLaurent Pinchart * pending interrupt. 7704976677f4d34df74d7207cae934b27f5d86feaceLaurent Pinchart */ 7714976677f4d34df74d7207cae934b27f5d86feaceLaurent Pinchart ldintr = lcdc_read(ch->lcdc, _LDINTR); 7724976677f4d34df74d7207cae934b27f5d86feaceLaurent Pinchart ldintr |= LDINTR_VEE | LDINTR_STATUS_MASK; 7734976677f4d34df74d7207cae934b27f5d86feaceLaurent Pinchart lcdc_write(ch->lcdc, _LDINTR, ldintr); 7744976677f4d34df74d7207cae934b27f5d86feaceLaurent Pinchart 7754976677f4d34df74d7207cae934b27f5d86feaceLaurent Pinchart ret = wait_for_completion_interruptible_timeout(&ch->vsync_completion, 7764976677f4d34df74d7207cae934b27f5d86feaceLaurent Pinchart msecs_to_jiffies(100)); 7774976677f4d34df74d7207cae934b27f5d86feaceLaurent Pinchart if (!ret) 7784976677f4d34df74d7207cae934b27f5d86feaceLaurent Pinchart return -ETIMEDOUT; 7794976677f4d34df74d7207cae934b27f5d86feaceLaurent Pinchart 7804976677f4d34df74d7207cae934b27f5d86feaceLaurent Pinchart return 0; 7814976677f4d34df74d7207cae934b27f5d86feaceLaurent Pinchart} 7824976677f4d34df74d7207cae934b27f5d86feaceLaurent Pinchart 783cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Dammstatic void sh_mobile_lcdc_start_stop(struct sh_mobile_lcdc_priv *priv, 784cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm int start) 785cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm{ 786cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm unsigned long tmp = lcdc_read(priv, _LDCNT2R); 787cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm int k; 788cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 789cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm /* start or stop the lcdc */ 790cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm if (start) 791ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart lcdc_write(priv, _LDCNT2R, tmp | LDCNT2R_DO); 792cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm else 793ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart lcdc_write(priv, _LDCNT2R, tmp & ~LDCNT2R_DO); 794cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 795cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm /* wait until power is applied/stopped on all channels */ 796cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm for (k = 0; k < ARRAY_SIZE(priv->ch); k++) 797cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm if (lcdc_read(priv, _LDCNT2R) & priv->ch[k].enabled) 798cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm while (1) { 799ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart tmp = lcdc_read_chan(&priv->ch[k], LDPMR) 800ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart & LDPMR_LPS; 801ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart if (start && tmp == LDPMR_LPS) 802cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm break; 803cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm if (!start && tmp == 0) 804cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm break; 805cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm cpu_relax(); 806cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm } 807cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 808cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm if (!start) 809cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm lcdc_write(priv, _LDDCKSTPR, 1); /* stop dotclock */ 810cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm} 811cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 8126011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetskistatic void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch) 8136011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski{ 8142d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart const struct fb_var_screeninfo *var = &ch->info->var; 8152d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart const struct fb_videomode *mode = &ch->display.mode; 8161c120deb60edd4c19a2109daa98f65f2ad3b9c06Guennadi Liakhovetski unsigned long h_total, hsync_pos, display_h_total; 8176011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski u32 tmp; 8186011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski 8196011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski tmp = ch->ldmt1r_value; 820ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart tmp |= (var->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : LDMT1R_VPOL; 821ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart tmp |= (var->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : LDMT1R_HPOL; 822b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart tmp |= (ch->cfg->flags & LCDC_FLAGS_DWPOL) ? LDMT1R_DWPOL : 0; 823b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart tmp |= (ch->cfg->flags & LCDC_FLAGS_DIPOL) ? LDMT1R_DIPOL : 0; 824b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart tmp |= (ch->cfg->flags & LCDC_FLAGS_DAPOL) ? LDMT1R_DAPOL : 0; 825b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart tmp |= (ch->cfg->flags & LCDC_FLAGS_HSCNT) ? LDMT1R_HSCNT : 0; 826b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart tmp |= (ch->cfg->flags & LCDC_FLAGS_DWCNT) ? LDMT1R_DWCNT : 0; 8276011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski lcdc_write_chan(ch, LDMT1R, tmp); 8286011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski 8296011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski /* setup SYS bus */ 830b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart lcdc_write_chan(ch, LDMT2R, ch->cfg->sys_bus_cfg.ldmt2r); 831b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart lcdc_write_chan(ch, LDMT3R, ch->cfg->sys_bus_cfg.ldmt3r); 8326011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski 8336011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski /* horizontal configuration */ 8342d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart h_total = mode->xres + mode->hsync_len + mode->left_margin 8352d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart + mode->right_margin; 8366011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski tmp = h_total / 8; /* HTCN */ 83758f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart tmp |= (min(mode->xres, ch->xres) / 8) << 16; /* HDCN */ 8386011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski lcdc_write_chan(ch, LDHCNR, tmp); 8396011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski 8402d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart hsync_pos = mode->xres + mode->right_margin; 8416011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski tmp = hsync_pos / 8; /* HSYNP */ 8422d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart tmp |= (mode->hsync_len / 8) << 16; /* HSYNW */ 8436011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski lcdc_write_chan(ch, LDHSYNR, tmp); 8446011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski 8456011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski /* vertical configuration */ 8462d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart tmp = mode->yres + mode->vsync_len + mode->upper_margin 8472d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart + mode->lower_margin; /* VTLN */ 84858f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart tmp |= min(mode->yres, ch->yres) << 16; /* VDLN */ 8496011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski lcdc_write_chan(ch, LDVLNR, tmp); 8506011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski 8512d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart tmp = mode->yres + mode->lower_margin; /* VSYNP */ 8522d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart tmp |= mode->vsync_len << 16; /* VSYNW */ 8536011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski lcdc_write_chan(ch, LDVSYNR, tmp); 8546011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski 8556011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski /* Adjust horizontal synchronisation for HDMI */ 8562d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart display_h_total = mode->xres + mode->hsync_len + mode->left_margin 8572d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart + mode->right_margin; 8582d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart tmp = ((mode->xres & 7) << 24) | ((display_h_total & 7) << 16) 8592d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart | ((mode->hsync_len & 7) << 8) | (hsync_pos & 7); 8606011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski lcdc_write_chan(ch, LDHAJR, tmp); 8616011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski} 8626011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski 863c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic void sh_mobile_lcdc_overlay_setup(struct sh_mobile_lcdc_overlay *ovl) 864c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 865c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart u32 format = 0; 866c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 867c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (!ovl->enabled) { 868c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart lcdc_write(ovl->channel->lcdc, LDBCR, LDBCR_UPC(ovl->index)); 869c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart lcdc_write_overlay(ovl, LDBnBSIFR(ovl->index), 0); 870c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart lcdc_write(ovl->channel->lcdc, LDBCR, 871c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart LDBCR_UPF(ovl->index) | LDBCR_UPD(ovl->index)); 872c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return; 873c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 874c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 875c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->base_addr_y = ovl->dma_handle; 876a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart ovl->base_addr_c = ovl->dma_handle 877a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart + ovl->xres_virtual * ovl->yres_virtual; 878c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 879c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart switch (ovl->mode) { 880c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case LCDC_OVERLAY_BLEND: 881c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart format = LDBBSIFR_EN | (ovl->alpha << LDBBSIFR_LAY_SHIFT); 882c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart break; 883c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 884c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case LCDC_OVERLAY_ROP3: 885c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart format = LDBBSIFR_EN | LDBBSIFR_BRSEL 886c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart | (ovl->rop3 << LDBBSIFR_ROP3_SHIFT); 887c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart break; 888c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 889c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 890c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart switch (ovl->format->fourcc) { 891c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case V4L2_PIX_FMT_RGB565: 892c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case V4L2_PIX_FMT_NV21: 893c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case V4L2_PIX_FMT_NV61: 894c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case V4L2_PIX_FMT_NV42: 895c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart format |= LDBBSIFR_SWPL | LDBBSIFR_SWPW; 896c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart break; 897c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case V4L2_PIX_FMT_BGR24: 898c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case V4L2_PIX_FMT_NV12: 899c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case V4L2_PIX_FMT_NV16: 900c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case V4L2_PIX_FMT_NV24: 901c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart format |= LDBBSIFR_SWPL | LDBBSIFR_SWPW | LDBBSIFR_SWPB; 902c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart break; 903c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case V4L2_PIX_FMT_BGR32: 904c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart default: 905c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart format |= LDBBSIFR_SWPL; 906c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart break; 907c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 908c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 909c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart switch (ovl->format->fourcc) { 910c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case V4L2_PIX_FMT_RGB565: 911c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart format |= LDBBSIFR_AL_1 | LDBBSIFR_RY | LDBBSIFR_RPKF_RGB16; 912c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart break; 913c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case V4L2_PIX_FMT_BGR24: 914c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart format |= LDBBSIFR_AL_1 | LDBBSIFR_RY | LDBBSIFR_RPKF_RGB24; 915c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart break; 916c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case V4L2_PIX_FMT_BGR32: 917c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart format |= LDBBSIFR_AL_PK | LDBBSIFR_RY | LDDFR_PKF_ARGB32; 918c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart break; 919c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case V4L2_PIX_FMT_NV12: 920c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case V4L2_PIX_FMT_NV21: 921c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart format |= LDBBSIFR_AL_1 | LDBBSIFR_CHRR_420; 922c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart break; 923c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case V4L2_PIX_FMT_NV16: 924c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case V4L2_PIX_FMT_NV61: 925c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart format |= LDBBSIFR_AL_1 | LDBBSIFR_CHRR_422; 926c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart break; 927c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case V4L2_PIX_FMT_NV24: 928c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case V4L2_PIX_FMT_NV42: 929c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart format |= LDBBSIFR_AL_1 | LDBBSIFR_CHRR_444; 930c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart break; 931c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 932c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 933c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart lcdc_write(ovl->channel->lcdc, LDBCR, LDBCR_UPC(ovl->index)); 934c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 935c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart lcdc_write_overlay(ovl, LDBnBSIFR(ovl->index), format); 936c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 937c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart lcdc_write_overlay(ovl, LDBnBSSZR(ovl->index), 938c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart (ovl->yres << LDBBSSZR_BVSS_SHIFT) | 939c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart (ovl->xres << LDBBSSZR_BHSS_SHIFT)); 940c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart lcdc_write_overlay(ovl, LDBnBLOCR(ovl->index), 941c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart (ovl->pos_y << LDBBLOCR_CVLC_SHIFT) | 942c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart (ovl->pos_x << LDBBLOCR_CHLC_SHIFT)); 943c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart lcdc_write_overlay(ovl, LDBnBSMWR(ovl->index), 944c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->pitch << LDBBSMWR_BSMW_SHIFT); 945c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 946c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart lcdc_write_overlay(ovl, LDBnBSAYR(ovl->index), ovl->base_addr_y); 947c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart lcdc_write_overlay(ovl, LDBnBSACR(ovl->index), ovl->base_addr_c); 948c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 949c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart lcdc_write(ovl->channel->lcdc, LDBCR, 950c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart LDBCR_UPF(ovl->index) | LDBCR_UPD(ovl->index)); 951c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 952c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 9539a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart/* 954d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchart * __sh_mobile_lcdc_start - Configure and start the LCDC 9559a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart * @priv: LCDC device 9569a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart * 9579a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart * Configure all enabled channels and start the LCDC device. All external 9589a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart * devices (clocks, MERAM, panels, ...) are not touched by this function. 9599a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart */ 9609a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchartstatic void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) 961cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm{ 962cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm struct sh_mobile_lcdc_chan *ch; 963cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm unsigned long tmp; 9649a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart int k, m; 9658564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm 9669a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart /* Enable LCDC channels. Read data from external memory, avoid using the 9679a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart * BEU for now. 9689a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart */ 9699a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart lcdc_write(priv, _LDCNT2R, priv->ch[0].enabled | priv->ch[1].enabled); 970cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 9719a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart /* Stop the LCDC first and disable all interrupts. */ 972cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm sh_mobile_lcdc_start_stop(priv, 0); 9739a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart lcdc_write(priv, _LDINTR, 0); 974cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 9759a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart /* Configure power supply, dot clocks and start them. */ 976cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm tmp = priv->lddckr; 977cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { 978cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm ch = &priv->ch[k]; 9799a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart if (!ch->enabled) 980cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm continue; 981cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 9829a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart /* Power supply */ 9839a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart lcdc_write_chan(ch, LDPMR, 0); 9849a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart 985b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart m = ch->cfg->clock_divider; 986cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm if (!m) 987cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm continue; 988cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 989505c7de51fe5ebb81fac096cb8cebd7cb45b7955Laurent Pinchart /* FIXME: sh7724 can only use 42, 48, 54 and 60 for the divider 990505c7de51fe5ebb81fac096cb8cebd7cb45b7955Laurent Pinchart * denominator. 991505c7de51fe5ebb81fac096cb8cebd7cb45b7955Laurent Pinchart */ 992505c7de51fe5ebb81fac096cb8cebd7cb45b7955Laurent Pinchart lcdc_write_chan(ch, LDDCKPAT1R, 0); 993505c7de51fe5ebb81fac096cb8cebd7cb45b7955Laurent Pinchart lcdc_write_chan(ch, LDDCKPAT2R, (1 << (m/2)) - 1); 994505c7de51fe5ebb81fac096cb8cebd7cb45b7955Laurent Pinchart 995cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm if (m == 1) 996ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart m = LDDCKR_MOSEL; 997cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm tmp |= m << (lcdc_chan_is_sublcd(ch) ? 8 : 0); 998cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm } 999cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 1000cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm lcdc_write(priv, _LDDCKR, tmp); 1001cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm lcdc_write(priv, _LDDCKSTPR, 0); 1002cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm lcdc_wait_bit(priv, _LDDCKSTPR, ~0, 0); 1003cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 10049a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart /* Setup geometry, format, frame buffer memory and operation mode. */ 1005cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { 1006cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm ch = &priv->ch[k]; 1007cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm if (!ch->enabled) 1008cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm continue; 1009cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 10106011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski sh_mobile_lcdc_geometry(ch); 1011cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 1012fc9e78e6b3d2ba2e96426527b8231f6b7c7b7b96Laurent Pinchart tmp = ch->format->lddfr; 1013edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart 1014fc9e78e6b3d2ba2e96426527b8231f6b7c7b7b96Laurent Pinchart if (ch->format->yuv) { 101558f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart switch (ch->colorspace) { 1016edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_COLORSPACE_REC709: 1017edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart tmp |= LDDFR_CF1; 101853b5031430bb3a7941b340b453afe4eabeb5340cDamian Hobson-Garcia break; 1019edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_COLORSPACE_JPEG: 1020edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart tmp |= LDDFR_CF0; 102153b5031430bb3a7941b340b453afe4eabeb5340cDamian Hobson-Garcia break; 102253b5031430bb3a7941b340b453afe4eabeb5340cDamian Hobson-Garcia } 1023417d48274e755e537bae60461558c1f63a4e14deMagnus Damm } 10247caa4342ca5b37d2d178b464c16badd4228b3b7bDamian Hobson-Garcia 10259a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart lcdc_write_chan(ch, LDDFR, tmp); 102672c04af9a2d57b7945cf3de8e71461bd80695d50Laurent Pinchart lcdc_write_chan(ch, LDMLSR, ch->line_size); 10279a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart lcdc_write_chan(ch, LDSA1R, ch->base_addr_y); 1028fc9e78e6b3d2ba2e96426527b8231f6b7c7b7b96Laurent Pinchart if (ch->format->yuv) 10299a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart lcdc_write_chan(ch, LDSA2R, ch->base_addr_c); 10307caa4342ca5b37d2d178b464c16badd4228b3b7bDamian Hobson-Garcia 10319a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart /* When using deferred I/O mode, configure the LCDC for one-shot 10329a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart * operation and enable the frame end interrupt. Otherwise use 10339a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart * continuous read mode. 10349a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart */ 10359a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart if (ch->ldmt1r_value & LDMT1R_IFM && 1036b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart ch->cfg->sys_bus_cfg.deferred_io_msec) { 10379a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart lcdc_write_chan(ch, LDSM1R, LDSM1R_OS); 10389a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart lcdc_write(priv, _LDINTR, LDINTR_FE); 10399a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart } else { 10409a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart lcdc_write_chan(ch, LDSM1R, 0); 10419a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart } 10429a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart } 10437caa4342ca5b37d2d178b464c16badd4228b3b7bDamian Hobson-Garcia 10449a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart /* Word and long word swap. */ 1045fc9e78e6b3d2ba2e96426527b8231f6b7c7b7b96Laurent Pinchart switch (priv->ch[0].format->fourcc) { 1046edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_PIX_FMT_RGB565: 1047edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_PIX_FMT_NV21: 1048edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_PIX_FMT_NV61: 1049edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_PIX_FMT_NV42: 1050edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart tmp = LDDDSR_LS | LDDDSR_WS; 1051edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart break; 1052edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_PIX_FMT_BGR24: 1053edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_PIX_FMT_NV12: 1054edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_PIX_FMT_NV16: 1055edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_PIX_FMT_NV24: 10569a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart tmp = LDDDSR_LS | LDDDSR_WS | LDDDSR_BS; 1057edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart break; 1058edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_PIX_FMT_BGR32: 1059edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart default: 1060edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart tmp = LDDDSR_LS; 1061edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart break; 10629a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart } 10639a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart lcdc_write(priv, _LDDDSR, tmp); 10647caa4342ca5b37d2d178b464c16badd4228b3b7bDamian Hobson-Garcia 10659a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart /* Enable the display output. */ 10669a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart lcdc_write(priv, _LDCNT1R, LDCNT1R_DE); 10679a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart sh_mobile_lcdc_start_stop(priv, 1); 10689a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart priv->started = 1; 10699a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart} 1070cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 10719a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchartstatic int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) 10729a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart{ 10739a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart struct sh_mobile_meram_info *mdev = priv->meram_dev; 10749a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart struct sh_mobile_lcdc_chan *ch; 10759a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart unsigned long tmp; 10769a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart int ret; 10779a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart int k; 1078cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 10799a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart /* enable clocks before accessing the hardware */ 10809a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { 10819a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart if (priv->ch[k].enabled) 10829a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart sh_mobile_lcdc_clk_on(priv); 10839a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart } 10848564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm 10859a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart /* reset */ 10869a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart lcdc_write(priv, _LDCNT2R, lcdc_read(priv, _LDCNT2R) | LDCNT2R_BR); 10879a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart lcdc_wait_bit(priv, _LDCNT2R, LDCNT2R_BR, 0); 10888564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm 10899a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { 1090b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart const struct sh_mobile_lcdc_panel_cfg *panel; 10918564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm 109237c5dcc21ddaa9f946c4d691996bb3076598b813Laurent Pinchart ch = &priv->ch[k]; 10939a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart if (!ch->enabled) 10949a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart continue; 10959a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart 1096b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart panel = &ch->cfg->panel_cfg; 1097afaad83b9c0d24eac88535cc5a8c6019f0c45bcbLaurent Pinchart if (panel->setup_sys) { 1098afaad83b9c0d24eac88535cc5a8c6019f0c45bcbLaurent Pinchart ret = panel->setup_sys(ch, &sh_mobile_lcdc_sys_bus_ops); 10999a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart if (ret) 11009a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart return ret; 11018564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm } 1102cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm } 1103cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 11049a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart /* Compute frame buffer base address and pitch for each channel. */ 11059a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { 11069a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart int pixelformat; 11074a2371772146b30113c9c837eb32b64f18376c0dLaurent Pinchart void *cache; 1108cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 11099a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart ch = &priv->ch[k]; 11109a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart if (!ch->enabled) 11119a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart continue; 1112cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 111358f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart ch->base_addr_y = ch->dma_handle; 1114a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart ch->base_addr_c = ch->dma_handle 1115a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart + ch->xres_virtual * ch->yres_virtual; 111672c04af9a2d57b7945cf3de8e71461bd80695d50Laurent Pinchart ch->line_size = ch->pitch; 11179a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart 11189a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart /* Enable MERAM if possible. */ 11196e729b416b44296f5ed503b40ac58c2bffb43cafLaurent Pinchart if (mdev == NULL || ch->cfg->meram_cfg == NULL) 11209a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart continue; 11219a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart 11224a2371772146b30113c9c837eb32b64f18376c0dLaurent Pinchart /* Free the allocated MERAM cache. */ 11234a2371772146b30113c9c837eb32b64f18376c0dLaurent Pinchart if (ch->cache) { 11246e729b416b44296f5ed503b40ac58c2bffb43cafLaurent Pinchart sh_mobile_meram_cache_free(mdev, ch->cache); 11254a2371772146b30113c9c837eb32b64f18376c0dLaurent Pinchart ch->cache = NULL; 11269a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart } 11279a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart 1128fc9e78e6b3d2ba2e96426527b8231f6b7c7b7b96Laurent Pinchart switch (ch->format->fourcc) { 1129edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_PIX_FMT_NV12: 1130edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_PIX_FMT_NV21: 1131edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_PIX_FMT_NV16: 1132edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_PIX_FMT_NV61: 11339a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart pixelformat = SH_MOBILE_MERAM_PF_NV; 1134edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart break; 1135edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_PIX_FMT_NV24: 1136edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_PIX_FMT_NV42: 1137edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart pixelformat = SH_MOBILE_MERAM_PF_NV24; 1138edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart break; 1139edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_PIX_FMT_RGB565: 1140edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_PIX_FMT_BGR24: 1141edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart case V4L2_PIX_FMT_BGR32: 1142edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart default: 1143edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart pixelformat = SH_MOBILE_MERAM_PF_RGB; 1144edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart break; 1145edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart } 11469a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart 11476e729b416b44296f5ed503b40ac58c2bffb43cafLaurent Pinchart cache = sh_mobile_meram_cache_alloc(mdev, ch->cfg->meram_cfg, 1148b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart ch->pitch, ch->yres, pixelformat, 114972c04af9a2d57b7945cf3de8e71461bd80695d50Laurent Pinchart &ch->line_size); 11504a2371772146b30113c9c837eb32b64f18376c0dLaurent Pinchart if (!IS_ERR(cache)) { 11516e729b416b44296f5ed503b40ac58c2bffb43cafLaurent Pinchart sh_mobile_meram_cache_update(mdev, cache, 115297d16fe69b6499a14a0c85c053f7bef54ce992a4Laurent Pinchart ch->base_addr_y, ch->base_addr_c, 115397d16fe69b6499a14a0c85c053f7bef54ce992a4Laurent Pinchart &ch->base_addr_y, &ch->base_addr_c); 11544a2371772146b30113c9c837eb32b64f18376c0dLaurent Pinchart ch->cache = cache; 115597d16fe69b6499a14a0c85c053f7bef54ce992a4Laurent Pinchart } 11569a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart } 11579a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart 1158c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart for (k = 0; k < ARRAY_SIZE(priv->overlays); ++k) { 1159c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_overlay *ovl = &priv->overlays[k]; 1160c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart sh_mobile_lcdc_overlay_setup(ovl); 1161c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 1162c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 11639a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart /* Start the LCDC. */ 11649a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart __sh_mobile_lcdc_start(priv); 11659a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart 11669a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart /* Setup deferred I/O, tell the board code to enable the panels, and 11679a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart * turn backlight on. 11689a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart */ 1169cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { 1170cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm ch = &priv->ch[k]; 117121bc1f024d0d4ea43fc0f2a43504e759261c7b18Magnus Damm if (!ch->enabled) 117221bc1f024d0d4ea43fc0f2a43504e759261c7b18Magnus Damm continue; 117321bc1f024d0d4ea43fc0f2a43504e759261c7b18Magnus Damm 1174b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart tmp = ch->cfg->sys_bus_cfg.deferred_io_msec; 11759a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart if (ch->ldmt1r_value & LDMT1R_IFM && tmp) { 11769a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart ch->defio.deferred_io = sh_mobile_lcdc_deferred_io; 11779a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart ch->defio.delay = msecs_to_jiffies(tmp); 11789a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart ch->info->fbdefio = &ch->defio; 11799a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart fb_deferred_io_init(ch->info); 11809a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart } 11819a217e3444ec0c3a0dba35f7b4221af6671da67bLaurent Pinchart 118237c5dcc21ddaa9f946c4d691996bb3076598b813Laurent Pinchart sh_mobile_lcdc_display_on(ch); 11833b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot 11843b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot if (ch->bl) { 11853b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot ch->bl->props.power = FB_BLANK_UNBLANK; 11863b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot backlight_update_status(ch->bl); 11873b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot } 1188cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm } 1189cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 1190cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm return 0; 1191cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm} 1192cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 1193cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Dammstatic void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv) 1194cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm{ 1195cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm struct sh_mobile_lcdc_chan *ch; 1196cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm int k; 1197cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 11982feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm /* clean up deferred io and ask board code to disable panel */ 1199cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { 1200cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm ch = &priv->ch[k]; 120121bc1f024d0d4ea43fc0f2a43504e759261c7b18Magnus Damm if (!ch->enabled) 120221bc1f024d0d4ea43fc0f2a43504e759261c7b18Magnus Damm continue; 12038564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm 12042feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm /* deferred io mode: 12052feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm * flush frame, and wait for frame end interrupt 12062feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm * clean up deferred io and enable clock 12072feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm */ 12085ef6b505d9df45558402bdb823a078840a6a26c4Guennadi Liakhovetski if (ch->info && ch->info->fbdefio) { 12092feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm ch->frame_end = 0; 1210e33afddca174171a68d57476ead8947476ab9240Paul Mundt schedule_delayed_work(&ch->info->deferred_work, 0); 12112feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm wait_event(ch->frame_end_wait, ch->frame_end); 1212e33afddca174171a68d57476ead8947476ab9240Paul Mundt fb_deferred_io_cleanup(ch->info); 1213e33afddca174171a68d57476ead8947476ab9240Paul Mundt ch->info->fbdefio = NULL; 12142feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm sh_mobile_lcdc_clk_on(priv); 12158564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm } 12162feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm 12173b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot if (ch->bl) { 12183b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot ch->bl->props.power = FB_BLANK_POWERDOWN; 12193b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot backlight_update_status(ch->bl); 12203b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot } 12213b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot 122237c5dcc21ddaa9f946c4d691996bb3076598b813Laurent Pinchart sh_mobile_lcdc_display_off(ch); 12237caa4342ca5b37d2d178b464c16badd4228b3b7bDamian Hobson-Garcia 12244a2371772146b30113c9c837eb32b64f18376c0dLaurent Pinchart /* Free the MERAM cache. */ 12254a2371772146b30113c9c837eb32b64f18376c0dLaurent Pinchart if (ch->cache) { 12266e729b416b44296f5ed503b40ac58c2bffb43cafLaurent Pinchart sh_mobile_meram_cache_free(priv->meram_dev, ch->cache); 12274a2371772146b30113c9c837eb32b64f18376c0dLaurent Pinchart ch->cache = 0; 12287caa4342ca5b37d2d178b464c16badd4228b3b7bDamian Hobson-Garcia } 12297caa4342ca5b37d2d178b464c16badd4228b3b7bDamian Hobson-Garcia 1230cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm } 1231cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 1232cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm /* stop the lcdc */ 12338e9bb19ef97d6594e735bee64b6d72103e350854Magnus Damm if (priv->started) { 12348e9bb19ef97d6594e735bee64b6d72103e350854Magnus Damm sh_mobile_lcdc_start_stop(priv, 0); 12358e9bb19ef97d6594e735bee64b6d72103e350854Magnus Damm priv->started = 0; 12368e9bb19ef97d6594e735bee64b6d72103e350854Magnus Damm } 1237b51339fff240ff179730f8963a758147fd60f3ecMagnus Damm 12388564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm /* stop clocks */ 12398564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm for (k = 0; k < ARRAY_SIZE(priv->ch); k++) 12408564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm if (priv->ch[k].enabled) 12418564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm sh_mobile_lcdc_clk_off(priv); 1242cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm} 1243cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 1244c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic int __sh_mobile_lcdc_check_var(struct fb_var_screeninfo *var, 1245c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct fb_info *info) 1246c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 1247c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (var->xres > MAX_XRES || var->yres > MAX_YRES) 1248c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return -EINVAL; 1249c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1250c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart /* Make sure the virtual resolution is at least as big as the visible 1251c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * resolution. 1252c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart */ 1253c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (var->xres_virtual < var->xres) 1254c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->xres_virtual = var->xres; 1255c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (var->yres_virtual < var->yres) 1256c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->yres_virtual = var->yres; 1257c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1258c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (sh_mobile_format_is_fourcc(var)) { 1259c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart const struct sh_mobile_lcdc_format_info *format; 1260c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1261c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart format = sh_mobile_format_info(var->grayscale); 1262c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (format == NULL) 1263c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return -EINVAL; 1264c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->bits_per_pixel = format->bpp; 1265c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1266c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart /* Default to RGB and JPEG color-spaces for RGB and YUV formats 1267c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * respectively. 1268c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart */ 1269c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (!format->yuv) 1270c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->colorspace = V4L2_COLORSPACE_SRGB; 1271c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart else if (var->colorspace != V4L2_COLORSPACE_REC709) 1272c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->colorspace = V4L2_COLORSPACE_JPEG; 1273c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } else { 1274c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (var->bits_per_pixel <= 16) { /* RGB 565 */ 1275c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->bits_per_pixel = 16; 1276c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->red.offset = 11; 1277c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->red.length = 5; 1278c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->green.offset = 5; 1279c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->green.length = 6; 1280c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->blue.offset = 0; 1281c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->blue.length = 5; 1282c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->transp.offset = 0; 1283c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->transp.length = 0; 1284c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } else if (var->bits_per_pixel <= 24) { /* RGB 888 */ 1285c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->bits_per_pixel = 24; 1286c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->red.offset = 16; 1287c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->red.length = 8; 1288c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->green.offset = 8; 1289c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->green.length = 8; 1290c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->blue.offset = 0; 1291c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->blue.length = 8; 1292c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->transp.offset = 0; 1293c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->transp.length = 0; 1294c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } else if (var->bits_per_pixel <= 32) { /* RGBA 888 */ 1295c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->bits_per_pixel = 32; 1296c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->red.offset = 16; 1297c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->red.length = 8; 1298c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->green.offset = 8; 1299c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->green.length = 8; 1300c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->blue.offset = 0; 1301c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->blue.length = 8; 1302c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->transp.offset = 24; 1303c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->transp.length = 8; 1304c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } else 1305c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return -EINVAL; 1306c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1307c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->red.msb_right = 0; 1308c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->green.msb_right = 0; 1309c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->blue.msb_right = 0; 1310c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->transp.msb_right = 0; 1311c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 1312c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1313c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart /* Make sure we don't exceed our allocated memory. */ 1314c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (var->xres_virtual * var->yres_virtual * var->bits_per_pixel / 8 > 1315c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info->fix.smem_len) 1316c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return -EINVAL; 1317c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1318c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return 0; 1319c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 1320c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1321c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart/* ----------------------------------------------------------------------------- 1322c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * Frame buffer operations - Overlays 1323c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart */ 1324c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1325c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic ssize_t 1326c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartoverlay_alpha_show(struct device *dev, struct device_attribute *attr, char *buf) 1327c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 1328c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct fb_info *info = dev_get_drvdata(dev); 1329c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_overlay *ovl = info->par; 1330c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1331c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return scnprintf(buf, PAGE_SIZE, "%u\n", ovl->alpha); 1332c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 1333c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1334c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic ssize_t 1335c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartoverlay_alpha_store(struct device *dev, struct device_attribute *attr, 1336c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart const char *buf, size_t count) 1337c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 1338c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct fb_info *info = dev_get_drvdata(dev); 1339c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_overlay *ovl = info->par; 1340c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart unsigned int alpha; 1341c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart char *endp; 1342c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1343c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart alpha = simple_strtoul(buf, &endp, 10); 1344c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (isspace(*endp)) 1345c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart endp++; 1346c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1347c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (endp - buf != count) 1348c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return -EINVAL; 1349c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1350c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (alpha > 255) 1351c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return -EINVAL; 1352c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1353c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (ovl->alpha != alpha) { 1354c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->alpha = alpha; 1355c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1356c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (ovl->mode == LCDC_OVERLAY_BLEND && ovl->enabled) 1357c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart sh_mobile_lcdc_overlay_setup(ovl); 1358c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 1359c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1360c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return count; 1361c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 1362c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1363c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic ssize_t 1364c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartoverlay_mode_show(struct device *dev, struct device_attribute *attr, char *buf) 1365c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 1366c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct fb_info *info = dev_get_drvdata(dev); 1367c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_overlay *ovl = info->par; 1368c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1369c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return scnprintf(buf, PAGE_SIZE, "%u\n", ovl->mode); 1370c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 1371c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1372c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic ssize_t 1373c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartoverlay_mode_store(struct device *dev, struct device_attribute *attr, 1374c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart const char *buf, size_t count) 1375c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 1376c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct fb_info *info = dev_get_drvdata(dev); 1377c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_overlay *ovl = info->par; 1378c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart unsigned int mode; 1379c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart char *endp; 1380c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1381c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart mode = simple_strtoul(buf, &endp, 10); 1382c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (isspace(*endp)) 1383c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart endp++; 1384c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1385c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (endp - buf != count) 1386c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return -EINVAL; 1387c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1388c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (mode != LCDC_OVERLAY_BLEND && mode != LCDC_OVERLAY_ROP3) 1389c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return -EINVAL; 1390c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1391c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (ovl->mode != mode) { 1392c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->mode = mode; 1393c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1394c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (ovl->enabled) 1395c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart sh_mobile_lcdc_overlay_setup(ovl); 1396c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 1397c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1398c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return count; 1399c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 1400c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1401c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic ssize_t 1402c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartoverlay_position_show(struct device *dev, struct device_attribute *attr, 1403c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart char *buf) 1404c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 1405c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct fb_info *info = dev_get_drvdata(dev); 1406c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_overlay *ovl = info->par; 1407c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1408c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return scnprintf(buf, PAGE_SIZE, "%d,%d\n", ovl->pos_x, ovl->pos_y); 1409c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 1410c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1411c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic ssize_t 1412c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartoverlay_position_store(struct device *dev, struct device_attribute *attr, 1413c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart const char *buf, size_t count) 1414c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 1415c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct fb_info *info = dev_get_drvdata(dev); 1416c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_overlay *ovl = info->par; 1417c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart char *endp; 1418c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart int pos_x; 1419c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart int pos_y; 1420c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1421c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart pos_x = simple_strtol(buf, &endp, 10); 1422c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (*endp != ',') 1423c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return -EINVAL; 1424c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1425c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart pos_y = simple_strtol(endp + 1, &endp, 10); 1426c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (isspace(*endp)) 1427c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart endp++; 1428c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1429c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (endp - buf != count) 1430c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return -EINVAL; 1431c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1432c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (ovl->pos_x != pos_x || ovl->pos_y != pos_y) { 1433c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->pos_x = pos_x; 1434c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->pos_y = pos_y; 1435c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1436c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (ovl->enabled) 1437c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart sh_mobile_lcdc_overlay_setup(ovl); 1438c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 1439c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1440c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return count; 1441c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 1442c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1443c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic ssize_t 1444c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartoverlay_rop3_show(struct device *dev, struct device_attribute *attr, char *buf) 1445c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 1446c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct fb_info *info = dev_get_drvdata(dev); 1447c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_overlay *ovl = info->par; 1448c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1449c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return scnprintf(buf, PAGE_SIZE, "%u\n", ovl->rop3); 1450c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 1451c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1452c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic ssize_t 1453c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartoverlay_rop3_store(struct device *dev, struct device_attribute *attr, 1454c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart const char *buf, size_t count) 1455c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 1456c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct fb_info *info = dev_get_drvdata(dev); 1457c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_overlay *ovl = info->par; 1458c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart unsigned int rop3; 1459c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart char *endp; 1460c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1461c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart rop3 = !!simple_strtoul(buf, &endp, 10); 1462c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (isspace(*endp)) 1463c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart endp++; 1464c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1465c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (endp - buf != count) 1466c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return -EINVAL; 1467c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1468c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (rop3 > 255) 1469c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return -EINVAL; 1470c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1471c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (ovl->rop3 != rop3) { 1472c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->rop3 = rop3; 1473c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1474c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (ovl->mode == LCDC_OVERLAY_ROP3 && ovl->enabled) 1475c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart sh_mobile_lcdc_overlay_setup(ovl); 1476c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 1477c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1478c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return count; 1479c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 1480c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1481c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic const struct device_attribute overlay_sysfs_attrs[] = { 1482c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart __ATTR(ovl_alpha, S_IRUGO|S_IWUSR, 1483c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart overlay_alpha_show, overlay_alpha_store), 1484c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart __ATTR(ovl_mode, S_IRUGO|S_IWUSR, 1485c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart overlay_mode_show, overlay_mode_store), 1486c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart __ATTR(ovl_position, S_IRUGO|S_IWUSR, 1487c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart overlay_position_show, overlay_position_store), 1488c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart __ATTR(ovl_rop3, S_IRUGO|S_IWUSR, 1489c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart overlay_rop3_show, overlay_rop3_store), 1490c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart}; 1491c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1492c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic const struct fb_fix_screeninfo sh_mobile_lcdc_overlay_fix = { 1493c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart .id = "SH Mobile LCDC", 1494c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart .type = FB_TYPE_PACKED_PIXELS, 1495c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart .visual = FB_VISUAL_TRUECOLOR, 1496c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart .accel = FB_ACCEL_NONE, 149715dede882e564601947f2ce4b647742c0351be6dLaurent Pinchart .xpanstep = 1, 1498c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart .ypanstep = 1, 1499c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart .ywrapstep = 0, 1500c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart .capabilities = FB_CAP_FOURCC, 1501c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart}; 1502c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1503c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic int sh_mobile_lcdc_overlay_pan(struct fb_var_screeninfo *var, 1504c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct fb_info *info) 1505c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 1506c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_overlay *ovl = info->par; 1507c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart unsigned long base_addr_y; 1508c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart unsigned long base_addr_c; 1509a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart unsigned long y_offset; 1510c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart unsigned long c_offset; 1511c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1512a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart if (!ovl->format->yuv) { 1513a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart y_offset = (var->yoffset * ovl->xres_virtual + var->xoffset) 1514a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart * ovl->format->bpp / 8; 1515a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart c_offset = 0; 1516a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart } else { 1517a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart unsigned int xsub = ovl->format->bpp < 24 ? 2 : 1; 1518a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart unsigned int ysub = ovl->format->bpp < 16 ? 2 : 1; 1519a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart 1520a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart y_offset = var->yoffset * ovl->xres_virtual + var->xoffset; 1521a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart c_offset = var->yoffset / ysub * ovl->xres_virtual * 2 / xsub 1522a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart + var->xoffset * 2 / xsub; 1523a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart } 1524c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1525a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart /* If the Y offset hasn't changed, the C offset hasn't either. There's 1526a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart * nothing to do in that case. 1527a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart */ 1528a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart if (y_offset == ovl->pan_y_offset) 1529a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart return 0; 1530c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1531c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart /* Set the source address for the next refresh */ 1532a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart base_addr_y = ovl->dma_handle + y_offset; 1533a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart base_addr_c = ovl->dma_handle + ovl->xres_virtual * ovl->yres_virtual 1534a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart + c_offset; 1535c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1536c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->base_addr_y = base_addr_y; 1537a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart ovl->base_addr_c = base_addr_c; 1538a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart ovl->pan_y_offset = y_offset; 1539c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 15408be7c66995bf06769dc4c5f7a62f3cd62a627e7eLaurent Pinchart lcdc_write(ovl->channel->lcdc, LDBCR, LDBCR_UPC(ovl->index)); 15418be7c66995bf06769dc4c5f7a62f3cd62a627e7eLaurent Pinchart 1542c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart lcdc_write_overlay(ovl, LDBnBSAYR(ovl->index), ovl->base_addr_y); 1543c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart lcdc_write_overlay(ovl, LDBnBSACR(ovl->index), ovl->base_addr_c); 1544c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 15458be7c66995bf06769dc4c5f7a62f3cd62a627e7eLaurent Pinchart lcdc_write(ovl->channel->lcdc, LDBCR, 15468be7c66995bf06769dc4c5f7a62f3cd62a627e7eLaurent Pinchart LDBCR_UPF(ovl->index) | LDBCR_UPD(ovl->index)); 15478be7c66995bf06769dc4c5f7a62f3cd62a627e7eLaurent Pinchart 1548c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return 0; 1549c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 1550c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1551c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic int sh_mobile_lcdc_overlay_ioctl(struct fb_info *info, unsigned int cmd, 1552c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart unsigned long arg) 1553c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 1554c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_overlay *ovl = info->par; 1555c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1556c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart switch (cmd) { 1557c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart case FBIO_WAITFORVSYNC: 1558c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return sh_mobile_lcdc_wait_for_vsync(ovl->channel); 1559c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1560c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart default: 1561c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return -ENOIOCTLCMD; 1562c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 1563c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 1564c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1565c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic int sh_mobile_lcdc_overlay_check_var(struct fb_var_screeninfo *var, 1566c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct fb_info *info) 1567c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 1568c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return __sh_mobile_lcdc_check_var(var, info); 1569c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 1570c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1571c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic int sh_mobile_lcdc_overlay_set_par(struct fb_info *info) 1572c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 1573c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_overlay *ovl = info->par; 1574c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1575c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->format = 1576c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart sh_mobile_format_info(sh_mobile_format_fourcc(&info->var)); 1577c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1578c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->xres = info->var.xres; 1579c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->xres_virtual = info->var.xres_virtual; 1580c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->yres = info->var.yres; 1581c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->yres_virtual = info->var.yres_virtual; 1582c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1583c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (ovl->format->yuv) 158416ca21c9a9f64577221c47d8d2f00d13b880aefaLaurent Pinchart ovl->pitch = info->var.xres_virtual; 1585c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart else 158616ca21c9a9f64577221c47d8d2f00d13b880aefaLaurent Pinchart ovl->pitch = info->var.xres_virtual * ovl->format->bpp / 8; 1587c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1588c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart sh_mobile_lcdc_overlay_setup(ovl); 1589c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1590c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info->fix.line_length = ovl->pitch; 1591c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1592c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (sh_mobile_format_is_fourcc(&info->var)) { 1593c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info->fix.type = FB_TYPE_FOURCC; 1594c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info->fix.visual = FB_VISUAL_FOURCC; 1595c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } else { 1596c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info->fix.type = FB_TYPE_PACKED_PIXELS; 1597c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info->fix.visual = FB_VISUAL_TRUECOLOR; 1598c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 1599c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1600c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return 0; 1601c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 1602c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1603c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart/* Overlay blanking. Disable the overlay when blanked. */ 1604c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic int sh_mobile_lcdc_overlay_blank(int blank, struct fb_info *info) 1605c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 1606c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_overlay *ovl = info->par; 1607c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1608c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->enabled = !blank; 1609c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart sh_mobile_lcdc_overlay_setup(ovl); 1610c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1611c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart /* Prevent the backlight from receiving a blanking event by returning 1612c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * a non-zero value. 1613c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart */ 1614c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return 1; 1615c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 1616c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1617bf10a53765b4435a5349a92a5a51753902ed86f1Hideki EIRAKUstatic int 1618bf10a53765b4435a5349a92a5a51753902ed86f1Hideki EIRAKUsh_mobile_lcdc_overlay_mmap(struct fb_info *info, struct vm_area_struct *vma) 1619bf10a53765b4435a5349a92a5a51753902ed86f1Hideki EIRAKU{ 1620bf10a53765b4435a5349a92a5a51753902ed86f1Hideki EIRAKU struct sh_mobile_lcdc_overlay *ovl = info->par; 1621bf10a53765b4435a5349a92a5a51753902ed86f1Hideki EIRAKU 1622bf10a53765b4435a5349a92a5a51753902ed86f1Hideki EIRAKU return dma_mmap_coherent(ovl->channel->lcdc->dev, vma, ovl->fb_mem, 1623bf10a53765b4435a5349a92a5a51753902ed86f1Hideki EIRAKU ovl->dma_handle, ovl->fb_size); 1624bf10a53765b4435a5349a92a5a51753902ed86f1Hideki EIRAKU} 1625bf10a53765b4435a5349a92a5a51753902ed86f1Hideki EIRAKU 1626c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic struct fb_ops sh_mobile_lcdc_overlay_ops = { 1627c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart .owner = THIS_MODULE, 1628c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart .fb_read = fb_sys_read, 1629c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart .fb_write = fb_sys_write, 1630c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart .fb_fillrect = sys_fillrect, 1631c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart .fb_copyarea = sys_copyarea, 1632c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart .fb_imageblit = sys_imageblit, 1633c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart .fb_blank = sh_mobile_lcdc_overlay_blank, 1634c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart .fb_pan_display = sh_mobile_lcdc_overlay_pan, 1635c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart .fb_ioctl = sh_mobile_lcdc_overlay_ioctl, 1636c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart .fb_check_var = sh_mobile_lcdc_overlay_check_var, 1637c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart .fb_set_par = sh_mobile_lcdc_overlay_set_par, 1638bf10a53765b4435a5349a92a5a51753902ed86f1Hideki EIRAKU .fb_mmap = sh_mobile_lcdc_overlay_mmap, 1639c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart}; 1640c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1641c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic void 1642c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartsh_mobile_lcdc_overlay_fb_unregister(struct sh_mobile_lcdc_overlay *ovl) 1643c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 1644c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct fb_info *info = ovl->info; 1645c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1646c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (info == NULL || info->dev == NULL) 1647c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return; 1648c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1649c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart unregister_framebuffer(ovl->info); 1650c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 1651c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1652c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic int __devinit 1653c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartsh_mobile_lcdc_overlay_fb_register(struct sh_mobile_lcdc_overlay *ovl) 1654c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 1655c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_priv *lcdc = ovl->channel->lcdc; 1656c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct fb_info *info = ovl->info; 1657c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart unsigned int i; 1658c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart int ret; 1659c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1660c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (info == NULL) 1661c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return 0; 1662c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1663c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ret = register_framebuffer(info); 1664c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (ret < 0) 1665c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return ret; 1666c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1667c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart dev_info(lcdc->dev, "registered %s/overlay %u as %dx%d %dbpp.\n", 1668c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart dev_name(lcdc->dev), ovl->index, info->var.xres, 1669c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info->var.yres, info->var.bits_per_pixel); 1670c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1671c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart for (i = 0; i < ARRAY_SIZE(overlay_sysfs_attrs); ++i) { 1672c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ret = device_create_file(info->dev, &overlay_sysfs_attrs[i]); 1673c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (ret < 0) 1674c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return ret; 1675c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 1676c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1677c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return 0; 1678c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 1679c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1680c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic void 1681c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartsh_mobile_lcdc_overlay_fb_cleanup(struct sh_mobile_lcdc_overlay *ovl) 1682c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 1683c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct fb_info *info = ovl->info; 1684c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1685c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (info == NULL || info->device == NULL) 1686c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return; 1687c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1688c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart framebuffer_release(info); 1689c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 1690c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1691c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic int __devinit 1692c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartsh_mobile_lcdc_overlay_fb_init(struct sh_mobile_lcdc_overlay *ovl) 1693c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 1694c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_priv *priv = ovl->channel->lcdc; 1695c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct fb_var_screeninfo *var; 1696c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct fb_info *info; 1697c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1698c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart /* Allocate and initialize the frame buffer device. */ 1699c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info = framebuffer_alloc(0, priv->dev); 1700c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (info == NULL) { 1701c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart dev_err(priv->dev, "unable to allocate fb_info\n"); 1702c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return -ENOMEM; 1703c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 1704c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1705c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->info = info; 1706c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1707c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info->flags = FBINFO_FLAG_DEFAULT; 1708c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info->fbops = &sh_mobile_lcdc_overlay_ops; 1709c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info->device = priv->dev; 1710c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info->screen_base = ovl->fb_mem; 1711c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info->par = ovl; 1712c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1713c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart /* Initialize fixed screen information. Restrict pan to 2 lines steps 1714c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * for NV12 and NV21. 1715c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart */ 1716c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info->fix = sh_mobile_lcdc_overlay_fix; 1717c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart snprintf(info->fix.id, sizeof(info->fix.id), 1718c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart "SH Mobile LCDC Overlay %u", ovl->index); 1719c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info->fix.smem_start = ovl->dma_handle; 1720c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info->fix.smem_len = ovl->fb_size; 1721c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info->fix.line_length = ovl->pitch; 1722c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1723c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (ovl->format->yuv) 1724c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info->fix.visual = FB_VISUAL_FOURCC; 1725c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart else 1726c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart info->fix.visual = FB_VISUAL_TRUECOLOR; 1727c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 172815dede882e564601947f2ce4b647742c0351be6dLaurent Pinchart switch (ovl->format->fourcc) { 172915dede882e564601947f2ce4b647742c0351be6dLaurent Pinchart case V4L2_PIX_FMT_NV12: 173015dede882e564601947f2ce4b647742c0351be6dLaurent Pinchart case V4L2_PIX_FMT_NV21: 1731ac33a207b13a70bbca6e58094e28bd92b9fc1ff3Laurent Pinchart info->fix.ypanstep = 2; 1732ac33a207b13a70bbca6e58094e28bd92b9fc1ff3Laurent Pinchart case V4L2_PIX_FMT_NV16: 1733ac33a207b13a70bbca6e58094e28bd92b9fc1ff3Laurent Pinchart case V4L2_PIX_FMT_NV61: 173415dede882e564601947f2ce4b647742c0351be6dLaurent Pinchart info->fix.xpanstep = 2; 173515dede882e564601947f2ce4b647742c0351be6dLaurent Pinchart } 1736c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1737c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart /* Initialize variable screen information. */ 1738c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var = &info->var; 1739c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart memset(var, 0, sizeof(*var)); 1740c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->xres = ovl->xres; 1741c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->yres = ovl->yres; 1742c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->xres_virtual = ovl->xres_virtual; 1743c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->yres_virtual = ovl->yres_virtual; 1744c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->activate = FB_ACTIVATE_NOW; 1745c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1746c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart /* Use the legacy API by default for RGB formats, and the FOURCC API 1747c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * for YUV formats. 1748c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart */ 1749c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (!ovl->format->yuv) 1750c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->bits_per_pixel = ovl->format->bpp; 1751c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart else 1752c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart var->grayscale = ovl->format->fourcc; 1753c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1754c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return sh_mobile_lcdc_overlay_check_var(var, info); 1755c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 1756c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 1757f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart/* ----------------------------------------------------------------------------- 1758c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * Frame buffer operations - main frame buffer 1759f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart */ 1760cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 1761cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Dammstatic int sh_mobile_lcdc_setcolreg(u_int regno, 1762cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm u_int red, u_int green, u_int blue, 1763cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm u_int transp, struct fb_info *info) 1764cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm{ 1765cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm u32 *palette = info->pseudo_palette; 1766cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 1767cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm if (regno >= PALETTE_NR) 1768cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm return -EINVAL; 1769cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 1770cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm /* only FB_VISUAL_TRUECOLOR supported */ 1771cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 1772cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm red >>= 16 - info->var.red.length; 1773cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm green >>= 16 - info->var.green.length; 1774cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm blue >>= 16 - info->var.blue.length; 1775cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm transp >>= 16 - info->var.transp.length; 1776cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 1777cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm palette[regno] = (red << info->var.red.offset) | 1778cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm (green << info->var.green.offset) | 1779cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm (blue << info->var.blue.offset) | 1780cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm (transp << info->var.transp.offset); 1781cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 1782cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm return 0; 1783cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm} 1784cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 17853281e54c80195b90ed12a5b6cddef4ab42e656e1Laurent Pinchartstatic const struct fb_fix_screeninfo sh_mobile_lcdc_fix = { 1786cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm .id = "SH Mobile LCDC", 1787cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm .type = FB_TYPE_PACKED_PIXELS, 1788cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm .visual = FB_VISUAL_TRUECOLOR, 1789cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm .accel = FB_ACCEL_NONE, 179015dede882e564601947f2ce4b647742c0351be6dLaurent Pinchart .xpanstep = 1, 17919dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy .ypanstep = 1, 17929dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy .ywrapstep = 0, 1793edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart .capabilities = FB_CAP_FOURCC, 1794cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm}; 1795cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 17968564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Dammstatic void sh_mobile_lcdc_fillrect(struct fb_info *info, 17978564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm const struct fb_fillrect *rect) 17988564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm{ 17998564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm sys_fillrect(info, rect); 18008564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm sh_mobile_lcdc_deferred_io_touch(info); 18018564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm} 18028564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm 18038564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Dammstatic void sh_mobile_lcdc_copyarea(struct fb_info *info, 18048564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm const struct fb_copyarea *area) 18058564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm{ 18068564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm sys_copyarea(info, area); 18078564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm sh_mobile_lcdc_deferred_io_touch(info); 18088564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm} 18098564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm 18108564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Dammstatic void sh_mobile_lcdc_imageblit(struct fb_info *info, 18118564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm const struct fb_image *image) 18128564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm{ 18138564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm sys_imageblit(info, image); 18148564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm sh_mobile_lcdc_deferred_io_touch(info); 18158564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm} 18168564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm 1817d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchartstatic int sh_mobile_lcdc_pan(struct fb_var_screeninfo *var, 1818d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchart struct fb_info *info) 18199dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy{ 18209dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy struct sh_mobile_lcdc_chan *ch = info->par; 182192e1f9a7ed613b36f3aaf8b04a79e2fd4fa37ec1Phil Edworthy struct sh_mobile_lcdc_priv *priv = ch->lcdc; 182292e1f9a7ed613b36f3aaf8b04a79e2fd4fa37ec1Phil Edworthy unsigned long ldrcntr; 1823a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart unsigned long base_addr_y, base_addr_c; 1824a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart unsigned long y_offset; 182553b5031430bb3a7941b340b453afe4eabeb5340cDamian Hobson-Garcia unsigned long c_offset; 182692e1f9a7ed613b36f3aaf8b04a79e2fd4fa37ec1Phil Edworthy 1827a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart if (!ch->format->yuv) { 1828a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart y_offset = (var->yoffset * ch->xres_virtual + var->xoffset) 1829a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart * ch->format->bpp / 8; 1830a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart c_offset = 0; 1831a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart } else { 1832a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart unsigned int xsub = ch->format->bpp < 24 ? 2 : 1; 1833a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart unsigned int ysub = ch->format->bpp < 16 ? 2 : 1; 18349dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy 1835a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart y_offset = var->yoffset * ch->xres_virtual + var->xoffset; 1836a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart c_offset = var->yoffset / ysub * ch->xres_virtual * 2 / xsub 1837a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart + var->xoffset * 2 / xsub; 1838a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart } 18399dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy 1840a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart /* If the Y offset hasn't changed, the C offset hasn't either. There's 1841a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart * nothing to do in that case. 1842a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart */ 1843a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart if (y_offset == ch->pan_y_offset) 1844a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart return 0; 18459dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy 184692e1f9a7ed613b36f3aaf8b04a79e2fd4fa37ec1Phil Edworthy /* Set the source address for the next refresh */ 1847a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart base_addr_y = ch->dma_handle + y_offset; 1848a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart base_addr_c = ch->dma_handle + ch->xres_virtual * ch->yres_virtual 1849a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart + c_offset; 185053b5031430bb3a7941b340b453afe4eabeb5340cDamian Hobson-Garcia 18516e729b416b44296f5ed503b40ac58c2bffb43cafLaurent Pinchart if (ch->cache) 18526e729b416b44296f5ed503b40ac58c2bffb43cafLaurent Pinchart sh_mobile_meram_cache_update(priv->meram_dev, ch->cache, 18536e729b416b44296f5ed503b40ac58c2bffb43cafLaurent Pinchart base_addr_y, base_addr_c, 18546e729b416b44296f5ed503b40ac58c2bffb43cafLaurent Pinchart &base_addr_y, &base_addr_c); 18557caa4342ca5b37d2d178b464c16badd4228b3b7bDamian Hobson-Garcia 185649d79ba2e39b5d3346e9e3ddf894eda72c743c85Laurent Pinchart ch->base_addr_y = base_addr_y; 185749d79ba2e39b5d3346e9e3ddf894eda72c743c85Laurent Pinchart ch->base_addr_c = base_addr_c; 1858a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart ch->pan_y_offset = y_offset; 18597caa4342ca5b37d2d178b464c16badd4228b3b7bDamian Hobson-Garcia 186049d79ba2e39b5d3346e9e3ddf894eda72c743c85Laurent Pinchart lcdc_write_chan_mirror(ch, LDSA1R, base_addr_y); 186158f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart if (ch->format->yuv) 186249d79ba2e39b5d3346e9e3ddf894eda72c743c85Laurent Pinchart lcdc_write_chan_mirror(ch, LDSA2R, base_addr_c); 186353b5031430bb3a7941b340b453afe4eabeb5340cDamian Hobson-Garcia 1864a4aa25f6e7885a42c90fe5f0a965403df6cbc943Laurent Pinchart ldrcntr = lcdc_read(priv, _LDRCNTR); 186592e1f9a7ed613b36f3aaf8b04a79e2fd4fa37ec1Phil Edworthy if (lcdc_chan_is_sublcd(ch)) 186692e1f9a7ed613b36f3aaf8b04a79e2fd4fa37ec1Phil Edworthy lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_SRS); 186792e1f9a7ed613b36f3aaf8b04a79e2fd4fa37ec1Phil Edworthy else 186892e1f9a7ed613b36f3aaf8b04a79e2fd4fa37ec1Phil Edworthy lcdc_write(ch->lcdc, _LDRCNTR, ldrcntr ^ LDRCNTR_MRS); 186992e1f9a7ed613b36f3aaf8b04a79e2fd4fa37ec1Phil Edworthy 187092e1f9a7ed613b36f3aaf8b04a79e2fd4fa37ec1Phil Edworthy 187192e1f9a7ed613b36f3aaf8b04a79e2fd4fa37ec1Phil Edworthy sh_mobile_lcdc_deferred_io_touch(info); 18729dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy 18739dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy return 0; 18749dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy} 18759dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy 1876d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchartstatic int sh_mobile_lcdc_ioctl(struct fb_info *info, unsigned int cmd, 1877d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchart unsigned long arg) 187840331b21f5fdb746e80fc609ef60ef71b5cd47d9Phil Edworthy{ 1879d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchart struct sh_mobile_lcdc_chan *ch = info->par; 188040331b21f5fdb746e80fc609ef60ef71b5cd47d9Phil Edworthy int retval; 188140331b21f5fdb746e80fc609ef60ef71b5cd47d9Phil Edworthy 188240331b21f5fdb746e80fc609ef60ef71b5cd47d9Phil Edworthy switch (cmd) { 188340331b21f5fdb746e80fc609ef60ef71b5cd47d9Phil Edworthy case FBIO_WAITFORVSYNC: 1884d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchart retval = sh_mobile_lcdc_wait_for_vsync(ch); 188540331b21f5fdb746e80fc609ef60ef71b5cd47d9Phil Edworthy break; 188640331b21f5fdb746e80fc609ef60ef71b5cd47d9Phil Edworthy 188740331b21f5fdb746e80fc609ef60ef71b5cd47d9Phil Edworthy default: 188840331b21f5fdb746e80fc609ef60ef71b5cd47d9Phil Edworthy retval = -ENOIOCTLCMD; 188940331b21f5fdb746e80fc609ef60ef71b5cd47d9Phil Edworthy break; 189040331b21f5fdb746e80fc609ef60ef71b5cd47d9Phil Edworthy } 189140331b21f5fdb746e80fc609ef60ef71b5cd47d9Phil Edworthy return retval; 189240331b21f5fdb746e80fc609ef60ef71b5cd47d9Phil Edworthy} 189340331b21f5fdb746e80fc609ef60ef71b5cd47d9Phil Edworthy 1894dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetskistatic void sh_mobile_fb_reconfig(struct fb_info *info) 1895dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski{ 1896dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski struct sh_mobile_lcdc_chan *ch = info->par; 18972d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart struct fb_var_screeninfo var; 18982d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart struct fb_videomode mode; 1899dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski struct fb_event event; 1900dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski int evnt = FB_EVENT_MODE_CHANGE_ALL; 1901dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski 1902dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski if (ch->use_count > 1 || (ch->use_count == 1 && !info->fbcon_par)) 1903dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski /* More framebuffer users are active */ 1904dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski return; 1905dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski 19062d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart fb_var_to_videomode(&mode, &info->var); 1907dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski 19082d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart if (fb_mode_is_equal(&ch->display.mode, &mode)) 1909dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski return; 1910dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski 1911dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski /* Display has been re-plugged, framebuffer is free now, reconfigure */ 19122d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart var = info->var; 19132d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart fb_videomode_to_var(&var, &ch->display.mode); 19142d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart var.width = ch->display.width; 19152d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart var.height = ch->display.height; 19162d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart var.activate = FB_ACTIVATE_NOW; 19172d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart 19182d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart if (fb_set_var(info, &var) < 0) 1919dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski /* Couldn't reconfigure, hopefully, can continue as before */ 1920dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski return; 1921dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski 1922dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski /* 1923dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski * fb_set_var() calls the notifier change internally, only if 1924dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski * FBINFO_MISC_USEREVENT flag is set. Since we do not want to fake a 1925dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski * user event, we have to call the chain ourselves. 1926dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski */ 1927dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski event.info = info; 19282d04559dc23bed905ed2904f2bbcbcc3f1a7fd91Laurent Pinchart event.data = &ch->display.mode; 1929dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski fb_notifier_call_chain(evnt, &event); 1930dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski} 1931dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski 1932dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski/* 1933dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski * Locking: both .fb_release() and .fb_open() are called with info->lock held if 1934dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski * user == 1, or with console sem held, if user == 0. 1935dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski */ 1936d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchartstatic int sh_mobile_lcdc_release(struct fb_info *info, int user) 1937dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski{ 1938dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski struct sh_mobile_lcdc_chan *ch = info->par; 1939dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski 1940dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski mutex_lock(&ch->open_lock); 1941dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski dev_dbg(info->dev, "%s(): %d users\n", __func__, ch->use_count); 1942dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski 1943dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski ch->use_count--; 1944dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski 1945dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski /* Nothing to reconfigure, when called from fbcon */ 1946dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski if (user) { 1947ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn console_lock(); 1948dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski sh_mobile_fb_reconfig(info); 1949ac751efa6a0d70f2c9daef5c7e3a92270f5c2dffTorben Hohn console_unlock(); 1950dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski } 1951dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski 1952dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski mutex_unlock(&ch->open_lock); 1953dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski 1954dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski return 0; 1955dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski} 1956dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski 1957d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchartstatic int sh_mobile_lcdc_open(struct fb_info *info, int user) 1958dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski{ 1959dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski struct sh_mobile_lcdc_chan *ch = info->par; 1960dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski 1961dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski mutex_lock(&ch->open_lock); 1962dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski ch->use_count++; 1963dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski 1964dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski dev_dbg(info->dev, "%s(): %d users\n", __func__, ch->use_count); 1965dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski mutex_unlock(&ch->open_lock); 1966dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski 1967dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski return 0; 1968dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski} 1969dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski 1970d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchartstatic int sh_mobile_lcdc_check_var(struct fb_var_screeninfo *var, 1971d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchart struct fb_info *info) 1972dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski{ 1973dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski struct sh_mobile_lcdc_chan *ch = info->par; 1974417d48274e755e537bae60461558c1f63a4e14deMagnus Damm struct sh_mobile_lcdc_priv *p = ch->lcdc; 19750386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart unsigned int best_dist = (unsigned int)-1; 19760386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart unsigned int best_xres = 0; 19770386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart unsigned int best_yres = 0; 19780386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart unsigned int i; 1979c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart int ret; 19800386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart 19810386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart /* If board code provides us with a list of available modes, make sure 19820386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart * we use one of them. Find the mode closest to the requested one. The 19830386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart * distance between two modes is defined as the size of the 19840386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart * non-overlapping parts of the two rectangles. 19850386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart */ 1986b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart for (i = 0; i < ch->cfg->num_modes; ++i) { 1987b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart const struct fb_videomode *mode = &ch->cfg->lcd_modes[i]; 19880386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart unsigned int dist; 19890386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart 19900386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart /* We can only round up. */ 19910386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart if (var->xres > mode->xres || var->yres > mode->yres) 19920386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart continue; 19930386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart 19940386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart dist = var->xres * var->yres + mode->xres * mode->yres 19950386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart - 2 * min(var->xres, mode->xres) 19960386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart * min(var->yres, mode->yres); 19970386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart 19980386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart if (dist < best_dist) { 19990386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart best_xres = mode->xres; 20000386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart best_yres = mode->yres; 20010386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart best_dist = dist; 20020386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart } 2003dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski } 2004417d48274e755e537bae60461558c1f63a4e14deMagnus Damm 20050386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart /* If no available mode can be used, return an error. */ 2006b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart if (ch->cfg->num_modes != 0) { 20070386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart if (best_dist == (unsigned int)-1) 20080386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart return -EINVAL; 20090386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart 20100386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart var->xres = best_xres; 20110386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart var->yres = best_yres; 20120386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart } 20130386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart 2014c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ret = __sh_mobile_lcdc_check_var(var, info); 2015c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (ret < 0) 2016c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return ret; 20170386219441d48e0f0902e9f145f0d75ad952d753Laurent Pinchart 2018edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart /* only accept the forced_fourcc for dual channel configurations */ 2019edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart if (p->forced_fourcc && 2020edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart p->forced_fourcc != sh_mobile_format_fourcc(var)) 2021417d48274e755e537bae60461558c1f63a4e14deMagnus Damm return -EINVAL; 2022417d48274e755e537bae60461558c1f63a4e14deMagnus Damm 2023dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski return 0; 2024dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski} 202540331b21f5fdb746e80fc609ef60ef71b5cd47d9Phil Edworthy 2026d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchartstatic int sh_mobile_lcdc_set_par(struct fb_info *info) 2027ed5bebf29e82beab3456901e26a495ae0a49ebadLaurent Pinchart{ 2028ed5bebf29e82beab3456901e26a495ae0a49ebadLaurent Pinchart struct sh_mobile_lcdc_chan *ch = info->par; 2029ed5bebf29e82beab3456901e26a495ae0a49ebadLaurent Pinchart int ret; 2030ed5bebf29e82beab3456901e26a495ae0a49ebadLaurent Pinchart 2031ed5bebf29e82beab3456901e26a495ae0a49ebadLaurent Pinchart sh_mobile_lcdc_stop(ch->lcdc); 203291fba48d59666718e3d3e86964755b80d39cdbddLaurent Pinchart 2033fc9e78e6b3d2ba2e96426527b8231f6b7c7b7b96Laurent Pinchart ch->format = sh_mobile_format_info(sh_mobile_format_fourcc(&info->var)); 203458f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart ch->colorspace = info->var.colorspace; 203558f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart 203658f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart ch->xres = info->var.xres; 203758f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart ch->xres_virtual = info->var.xres_virtual; 203858f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart ch->yres = info->var.yres; 203958f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart ch->yres_virtual = info->var.yres_virtual; 204058f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart 204158f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart if (ch->format->yuv) 204216ca21c9a9f64577221c47d8d2f00d13b880aefaLaurent Pinchart ch->pitch = info->var.xres_virtual; 204358f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart else 204416ca21c9a9f64577221c47d8d2f00d13b880aefaLaurent Pinchart ch->pitch = info->var.xres_virtual * ch->format->bpp / 8; 2045fc9e78e6b3d2ba2e96426527b8231f6b7c7b7b96Laurent Pinchart 2046ed5bebf29e82beab3456901e26a495ae0a49ebadLaurent Pinchart ret = sh_mobile_lcdc_start(ch->lcdc); 204758f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart if (ret < 0) 2048ed5bebf29e82beab3456901e26a495ae0a49ebadLaurent Pinchart dev_err(info->dev, "%s: unable to restart LCDC\n", __func__); 204958f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart 205058f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart info->fix.line_length = ch->pitch; 2051ed5bebf29e82beab3456901e26a495ae0a49ebadLaurent Pinchart 2052edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart if (sh_mobile_format_is_fourcc(&info->var)) { 2053edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart info->fix.type = FB_TYPE_FOURCC; 2054edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart info->fix.visual = FB_VISUAL_FOURCC; 2055edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart } else { 2056edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart info->fix.type = FB_TYPE_PACKED_PIXELS; 2057edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart info->fix.visual = FB_VISUAL_TRUECOLOR; 2058edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart } 2059edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart 2060ed5bebf29e82beab3456901e26a495ae0a49ebadLaurent Pinchart return ret; 2061ed5bebf29e82beab3456901e26a495ae0a49ebadLaurent Pinchart} 2062ed5bebf29e82beab3456901e26a495ae0a49ebadLaurent Pinchart 20638857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot/* 20648857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot * Screen blanking. Behavior is as follows: 20658857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot * FB_BLANK_UNBLANK: screen unblanked, clocks enabled 20668857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot * FB_BLANK_NORMAL: screen blanked, clocks enabled 20678857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot * FB_BLANK_VSYNC, 20688857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot * FB_BLANK_HSYNC, 20698857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot * FB_BLANK_POWEROFF: screen blanked, clocks disabled 20708857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot */ 20718857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbotstatic int sh_mobile_lcdc_blank(int blank, struct fb_info *info) 20728857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot{ 20738857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot struct sh_mobile_lcdc_chan *ch = info->par; 20748857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot struct sh_mobile_lcdc_priv *p = ch->lcdc; 20758857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot 20768857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot /* blank the screen? */ 20778857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot if (blank > FB_BLANK_UNBLANK && ch->blank_status == FB_BLANK_UNBLANK) { 20788857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot struct fb_fillrect rect = { 207958f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart .width = ch->xres, 208058f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart .height = ch->yres, 20818857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot }; 20828857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot sh_mobile_lcdc_fillrect(info, &rect); 20838857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot } 20848857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot /* turn clocks on? */ 20858857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot if (blank <= FB_BLANK_NORMAL && ch->blank_status > FB_BLANK_NORMAL) { 20868857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot sh_mobile_lcdc_clk_on(p); 20878857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot } 20888857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot /* turn clocks off? */ 20898857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot if (blank > FB_BLANK_NORMAL && ch->blank_status <= FB_BLANK_NORMAL) { 20908857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot /* make sure the screen is updated with the black fill before 20918857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot * switching the clocks off. one vsync is not enough since 20928857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot * blanking may occur in the middle of a refresh. deferred io 20938857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot * mode will reenable the clocks and update the screen in time, 20948857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot * so it does not need this. */ 20958857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot if (!info->fbdefio) { 2096d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchart sh_mobile_lcdc_wait_for_vsync(ch); 2097d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchart sh_mobile_lcdc_wait_for_vsync(ch); 20988857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot } 20998857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot sh_mobile_lcdc_clk_off(p); 21008857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot } 21018857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot 21028857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot ch->blank_status = blank; 21038857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot return 0; 21048857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot} 21058857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot 2106bf10a53765b4435a5349a92a5a51753902ed86f1Hideki EIRAKUstatic int 2107bf10a53765b4435a5349a92a5a51753902ed86f1Hideki EIRAKUsh_mobile_lcdc_mmap(struct fb_info *info, struct vm_area_struct *vma) 2108bf10a53765b4435a5349a92a5a51753902ed86f1Hideki EIRAKU{ 2109bf10a53765b4435a5349a92a5a51753902ed86f1Hideki EIRAKU struct sh_mobile_lcdc_chan *ch = info->par; 2110bf10a53765b4435a5349a92a5a51753902ed86f1Hideki EIRAKU 2111bf10a53765b4435a5349a92a5a51753902ed86f1Hideki EIRAKU return dma_mmap_coherent(ch->lcdc->dev, vma, ch->fb_mem, 2112bf10a53765b4435a5349a92a5a51753902ed86f1Hideki EIRAKU ch->dma_handle, ch->fb_size); 2113bf10a53765b4435a5349a92a5a51753902ed86f1Hideki EIRAKU} 2114bf10a53765b4435a5349a92a5a51753902ed86f1Hideki EIRAKU 2115cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Dammstatic struct fb_ops sh_mobile_lcdc_ops = { 21169dd38819c2257375ea05bcb92b1f607a1d523c84Phil Edworthy .owner = THIS_MODULE, 2117cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm .fb_setcolreg = sh_mobile_lcdc_setcolreg, 21182540c111ead82cad605ec2b14a1905ad914cc124Magnus Damm .fb_read = fb_sys_read, 21192540c111ead82cad605ec2b14a1905ad914cc124Magnus Damm .fb_write = fb_sys_write, 21208564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm .fb_fillrect = sh_mobile_lcdc_fillrect, 21218564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm .fb_copyarea = sh_mobile_lcdc_copyarea, 21228564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm .fb_imageblit = sh_mobile_lcdc_imageblit, 21238857b9aa7e64a70852545ee01fa638481cb08a76Alexandre Courbot .fb_blank = sh_mobile_lcdc_blank, 2124d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchart .fb_pan_display = sh_mobile_lcdc_pan, 2125d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchart .fb_ioctl = sh_mobile_lcdc_ioctl, 2126d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchart .fb_open = sh_mobile_lcdc_open, 2127d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchart .fb_release = sh_mobile_lcdc_release, 2128d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchart .fb_check_var = sh_mobile_lcdc_check_var, 2129d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchart .fb_set_par = sh_mobile_lcdc_set_par, 2130bf10a53765b4435a5349a92a5a51753902ed86f1Hideki EIRAKU .fb_mmap = sh_mobile_lcdc_mmap, 2131cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm}; 2132cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 2133a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchartstatic void 2134a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchartsh_mobile_lcdc_channel_fb_unregister(struct sh_mobile_lcdc_chan *ch) 2135a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart{ 2136a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart if (ch->info && ch->info->dev) 2137a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart unregister_framebuffer(ch->info); 2138a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart} 2139a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2140a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchartstatic int __devinit 2141a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchartsh_mobile_lcdc_channel_fb_register(struct sh_mobile_lcdc_chan *ch) 2142a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart{ 2143a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart struct fb_info *info = ch->info; 2144a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart int ret; 2145a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2146a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart if (info->fbdefio) { 2147a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart ch->sglist = vmalloc(sizeof(struct scatterlist) * 2148a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart ch->fb_size >> PAGE_SHIFT); 2149a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart if (!ch->sglist) { 2150a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart dev_err(ch->lcdc->dev, "cannot allocate sglist\n"); 2151a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart return -ENOMEM; 2152a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart } 2153a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart } 2154a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2155a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart info->bl_dev = ch->bl; 2156a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2157a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart ret = register_framebuffer(info); 2158a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart if (ret < 0) 2159a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart return ret; 2160a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2161a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart dev_info(ch->lcdc->dev, "registered %s/%s as %dx%d %dbpp.\n", 2162b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart dev_name(ch->lcdc->dev), (ch->cfg->chan == LCDC_CHAN_MAINLCD) ? 2163a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart "mainlcd" : "sublcd", info->var.xres, info->var.yres, 2164a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart info->var.bits_per_pixel); 2165a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2166a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart /* deferred io mode: disable clock to save power */ 2167a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart if (info->fbdefio || info->state == FBINFO_STATE_SUSPENDED) 2168a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart sh_mobile_lcdc_clk_off(ch->lcdc); 2169a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2170a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart return ret; 2171a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart} 2172a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2173a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchartstatic void 2174a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchartsh_mobile_lcdc_channel_fb_cleanup(struct sh_mobile_lcdc_chan *ch) 2175a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart{ 2176a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart struct fb_info *info = ch->info; 2177a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2178a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart if (!info || !info->device) 2179a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart return; 2180a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2181a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart if (ch->sglist) 2182a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart vfree(ch->sglist); 2183a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2184a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart fb_dealloc_cmap(&info->cmap); 2185a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart framebuffer_release(info); 2186a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart} 2187a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2188a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchartstatic int __devinit 2189a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchartsh_mobile_lcdc_channel_fb_init(struct sh_mobile_lcdc_chan *ch, 2190352d6138779e22c5340803d5a32fc332ad2e5e1dLaurent Pinchart const struct fb_videomode *modes, 2191a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart unsigned int num_modes) 2192a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart{ 2193a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart struct sh_mobile_lcdc_priv *priv = ch->lcdc; 2194a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart struct fb_var_screeninfo *var; 2195a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart struct fb_info *info; 2196a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart int ret; 2197a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2198a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart /* Allocate and initialize the frame buffer device. Create the modes 2199a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart * list and allocate the color map. 2200a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart */ 2201a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart info = framebuffer_alloc(0, priv->dev); 2202a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart if (info == NULL) { 2203a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart dev_err(priv->dev, "unable to allocate fb_info\n"); 2204a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart return -ENOMEM; 2205a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart } 2206a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2207a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart ch->info = info; 2208a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2209a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart info->flags = FBINFO_FLAG_DEFAULT; 2210a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart info->fbops = &sh_mobile_lcdc_ops; 2211a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart info->device = priv->dev; 2212a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart info->screen_base = ch->fb_mem; 2213a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart info->pseudo_palette = &ch->pseudo_palette; 2214a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart info->par = ch; 2215a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2216352d6138779e22c5340803d5a32fc332ad2e5e1dLaurent Pinchart fb_videomode_to_modelist(modes, num_modes, &info->modelist); 2217a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2218a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart ret = fb_alloc_cmap(&info->cmap, PALETTE_NR, 0); 2219a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart if (ret < 0) { 2220a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart dev_err(priv->dev, "unable to allocate cmap\n"); 2221a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart return ret; 2222a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart } 2223a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2224a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart /* Initialize fixed screen information. Restrict pan to 2 lines steps 2225a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart * for NV12 and NV21. 2226a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart */ 2227a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart info->fix = sh_mobile_lcdc_fix; 2228a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart info->fix.smem_start = ch->dma_handle; 2229a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart info->fix.smem_len = ch->fb_size; 223058f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart info->fix.line_length = ch->pitch; 223158f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart 223258f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart if (ch->format->yuv) 223358f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart info->fix.visual = FB_VISUAL_FOURCC; 223458f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart else 223558f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart info->fix.visual = FB_VISUAL_TRUECOLOR; 223658f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart 223715dede882e564601947f2ce4b647742c0351be6dLaurent Pinchart switch (ch->format->fourcc) { 223815dede882e564601947f2ce4b647742c0351be6dLaurent Pinchart case V4L2_PIX_FMT_NV12: 223915dede882e564601947f2ce4b647742c0351be6dLaurent Pinchart case V4L2_PIX_FMT_NV21: 2240ac33a207b13a70bbca6e58094e28bd92b9fc1ff3Laurent Pinchart info->fix.ypanstep = 2; 2241ac33a207b13a70bbca6e58094e28bd92b9fc1ff3Laurent Pinchart case V4L2_PIX_FMT_NV16: 2242ac33a207b13a70bbca6e58094e28bd92b9fc1ff3Laurent Pinchart case V4L2_PIX_FMT_NV61: 224315dede882e564601947f2ce4b647742c0351be6dLaurent Pinchart info->fix.xpanstep = 2; 224415dede882e564601947f2ce4b647742c0351be6dLaurent Pinchart } 2245a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2246a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart /* Initialize variable screen information using the first mode as 2247bd5f2c6911c210af52fa4dc4cf504043ff8a4971Laurent Pinchart * default. 2248a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart */ 2249a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart var = &info->var; 2250352d6138779e22c5340803d5a32fc332ad2e5e1dLaurent Pinchart fb_videomode_to_var(var, modes); 2251856e8dfe6efed7cf35bc6bf827f030a164bee083Laurent Pinchart var->width = ch->display.width; 2252856e8dfe6efed7cf35bc6bf827f030a164bee083Laurent Pinchart var->height = ch->display.height; 2253bd5f2c6911c210af52fa4dc4cf504043ff8a4971Laurent Pinchart var->xres_virtual = ch->xres_virtual; 2254bd5f2c6911c210af52fa4dc4cf504043ff8a4971Laurent Pinchart var->yres_virtual = ch->yres_virtual; 2255a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart var->activate = FB_ACTIVATE_NOW; 2256a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2257a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart /* Use the legacy API by default for RGB formats, and the FOURCC API 2258a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart * for YUV formats. 2259a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart */ 2260a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart if (!ch->format->yuv) 2261a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart var->bits_per_pixel = ch->format->bpp; 2262a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart else 2263a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart var->grayscale = ch->format->fourcc; 2264a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2265d7ad33421863308fe7ddf865737d4d83b64e5b81Laurent Pinchart ret = sh_mobile_lcdc_check_var(var, info); 2266a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart if (ret) 2267a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart return ret; 2268a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2269a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart return 0; 2270a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart} 2271a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2272f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart/* ----------------------------------------------------------------------------- 2273f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart * Backlight 2274f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart */ 2275f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 22763b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbotstatic int sh_mobile_lcdc_update_bl(struct backlight_device *bdev) 22773b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot{ 22783b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot struct sh_mobile_lcdc_chan *ch = bl_get_data(bdev); 22793b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot int brightness = bdev->props.brightness; 22803b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot 22813b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot if (bdev->props.power != FB_BLANK_UNBLANK || 22823b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot bdev->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK)) 22833b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot brightness = 0; 22843b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot 2285b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart return ch->cfg->bl_info.set_brightness(brightness); 22863b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot} 22873b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot 22883b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbotstatic int sh_mobile_lcdc_get_brightness(struct backlight_device *bdev) 22893b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot{ 22903b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot struct sh_mobile_lcdc_chan *ch = bl_get_data(bdev); 22913b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot 2292b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart return ch->cfg->bl_info.get_brightness(); 22933b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot} 22943b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot 22953b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbotstatic int sh_mobile_lcdc_check_fb(struct backlight_device *bdev, 22963b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot struct fb_info *info) 22973b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot{ 22983b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot return (info->bl_dev == bdev); 22993b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot} 23003b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot 23013b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbotstatic struct backlight_ops sh_mobile_lcdc_bl_ops = { 23023b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot .options = BL_CORE_SUSPENDRESUME, 23033b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot .update_status = sh_mobile_lcdc_update_bl, 23043b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot .get_brightness = sh_mobile_lcdc_get_brightness, 23053b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot .check_fb = sh_mobile_lcdc_check_fb, 23063b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot}; 23073b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot 23083b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbotstatic struct backlight_device *sh_mobile_lcdc_bl_probe(struct device *parent, 23093b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot struct sh_mobile_lcdc_chan *ch) 23103b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot{ 23113b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot struct backlight_device *bl; 23123b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot 2313b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart bl = backlight_device_register(ch->cfg->bl_info.name, parent, ch, 23143b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot &sh_mobile_lcdc_bl_ops, NULL); 2315beee1f20a185c7e79fd33bb83e04fe44ecd75af3Dan Carpenter if (IS_ERR(bl)) { 2316beee1f20a185c7e79fd33bb83e04fe44ecd75af3Dan Carpenter dev_err(parent, "unable to register backlight device: %ld\n", 2317beee1f20a185c7e79fd33bb83e04fe44ecd75af3Dan Carpenter PTR_ERR(bl)); 23183b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot return NULL; 23193b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot } 23203b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot 2321b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart bl->props.max_brightness = ch->cfg->bl_info.max_brightness; 23223b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot bl->props.brightness = bl->props.max_brightness; 23233b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot backlight_update_status(bl); 23243b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot 23253b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot return bl; 23263b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot} 23273b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot 23283b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbotstatic void sh_mobile_lcdc_bl_remove(struct backlight_device *bdev) 23293b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot{ 23303b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot backlight_device_unregister(bdev); 23313b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot} 23323b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot 2333f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart/* ----------------------------------------------------------------------------- 2334f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart * Power management 2335f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart */ 2336f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 23372feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Dammstatic int sh_mobile_lcdc_suspend(struct device *dev) 23382feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm{ 23392feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm struct platform_device *pdev = to_platform_device(dev); 23402feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm 23412feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm sh_mobile_lcdc_stop(platform_get_drvdata(pdev)); 23422feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm return 0; 23432feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm} 23442feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm 23452feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Dammstatic int sh_mobile_lcdc_resume(struct device *dev) 23462feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm{ 23472feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm struct platform_device *pdev = to_platform_device(dev); 23482feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm 23492feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm return sh_mobile_lcdc_start(platform_get_drvdata(pdev)); 23502feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm} 23512feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm 23520246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Dammstatic int sh_mobile_lcdc_runtime_suspend(struct device *dev) 23530246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Damm{ 23540246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Damm struct platform_device *pdev = to_platform_device(dev); 23552427bb241b1db35c6e699ad55adf4a30083b79cdLaurent Pinchart struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev); 23560246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Damm 23570246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Damm /* turn off LCDC hardware */ 23582427bb241b1db35c6e699ad55adf4a30083b79cdLaurent Pinchart lcdc_write(priv, _LDCNT1R, 0); 23592427bb241b1db35c6e699ad55adf4a30083b79cdLaurent Pinchart 23600246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Damm return 0; 23610246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Damm} 23620246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Damm 23630246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Dammstatic int sh_mobile_lcdc_runtime_resume(struct device *dev) 23640246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Damm{ 23650246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Damm struct platform_device *pdev = to_platform_device(dev); 23662427bb241b1db35c6e699ad55adf4a30083b79cdLaurent Pinchart struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev); 23670246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Damm 23682427bb241b1db35c6e699ad55adf4a30083b79cdLaurent Pinchart __sh_mobile_lcdc_start(priv); 23690246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Damm 23700246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Damm return 0; 23710246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Damm} 23720246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Damm 2373471452104b8520337ae2fb48c4e61cd4896e025dAlexey Dobriyanstatic const struct dev_pm_ops sh_mobile_lcdc_dev_pm_ops = { 23742feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm .suspend = sh_mobile_lcdc_suspend, 23752feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm .resume = sh_mobile_lcdc_resume, 23760246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Damm .runtime_suspend = sh_mobile_lcdc_runtime_suspend, 23770246c4712c40294bd5e8335f0c15a38c8e52709fMagnus Damm .runtime_resume = sh_mobile_lcdc_runtime_resume, 23782feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm}; 23792feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm 2380f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart/* ----------------------------------------------------------------------------- 2381f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart * Framebuffer notifier 2382f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart */ 2383f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 23846de9edd5bde0cdfea12e9948690e53ec669c3018Guennadi Liakhovetski/* locking: called with info->lock held */ 23856011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetskistatic int sh_mobile_lcdc_notify(struct notifier_block *nb, 23866011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski unsigned long action, void *data) 23876011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski{ 23886011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski struct fb_event *event = data; 23896011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski struct fb_info *info = event->info; 23906011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski struct sh_mobile_lcdc_chan *ch = info->par; 23916011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski 23926011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski if (&ch->lcdc->notifier != nb) 2393baf163749952ca5e33dd2d6a74da023e385c3a00Guennadi Liakhovetski return NOTIFY_DONE; 23946011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski 23956011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski dev_dbg(info->dev, "%s(): action = %lu, data = %p\n", 23966011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski __func__, action, event->data); 23976011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski 23986011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski switch(action) { 23996011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski case FB_EVENT_SUSPEND: 240037c5dcc21ddaa9f946c4d691996bb3076598b813Laurent Pinchart sh_mobile_lcdc_display_off(ch); 2401afe417c0355154c8b2547619771d6053b3c0aad7Guennadi Liakhovetski sh_mobile_lcdc_stop(ch->lcdc); 24026011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski break; 24036011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski case FB_EVENT_RESUME: 2404dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski mutex_lock(&ch->open_lock); 2405dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski sh_mobile_fb_reconfig(info); 2406dd210503b77ae04adfdb25ca45536c4f7e33edb1Guennadi Liakhovetski mutex_unlock(&ch->open_lock); 24076011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski 240837c5dcc21ddaa9f946c4d691996bb3076598b813Laurent Pinchart sh_mobile_lcdc_display_on(ch); 2409ebe5e12d00f4785092a9650845ad3451bbf4b311Guennadi Liakhovetski sh_mobile_lcdc_start(ch->lcdc); 24106011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski } 24116011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski 2412baf163749952ca5e33dd2d6a74da023e385c3a00Guennadi Liakhovetski return NOTIFY_OK; 24136011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski} 24146011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski 2415f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart/* ----------------------------------------------------------------------------- 2416f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart * Probe/remove and driver init/exit 2417f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart */ 2418f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 2419217e9c4353aa86f0c7eeb4c275bca73ea8b53be1Laurent Pinchartstatic const struct fb_videomode default_720p __devinitconst = { 2420f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart .name = "HDMI 720p", 2421f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart .xres = 1280, 2422f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart .yres = 720, 2423f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 2424f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart .left_margin = 220, 2425f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart .right_margin = 110, 2426f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart .hsync_len = 40, 2427f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 2428f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart .upper_margin = 20, 2429f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart .lower_margin = 5, 2430f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart .vsync_len = 5, 2431f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 2432f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart .pixclock = 13468, 2433f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart .refresh = 60, 2434f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart .sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT, 2435f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart}; 2436f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 2437b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchartstatic int sh_mobile_lcdc_remove(struct platform_device *pdev) 2438b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart{ 2439b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev); 2440c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart unsigned int i; 2441b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart 2442b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart fb_unregister_client(&priv->notifier); 2443b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart 2444c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart for (i = 0; i < ARRAY_SIZE(priv->overlays); i++) 2445c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart sh_mobile_lcdc_overlay_fb_unregister(&priv->overlays[i]); 2446b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart for (i = 0; i < ARRAY_SIZE(priv->ch); i++) 2447a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart sh_mobile_lcdc_channel_fb_unregister(&priv->ch[i]); 2448b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart 2449b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart sh_mobile_lcdc_stop(priv); 2450b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart 2451c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart for (i = 0; i < ARRAY_SIZE(priv->overlays); i++) { 2452c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_overlay *ovl = &priv->overlays[i]; 2453c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 2454c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart sh_mobile_lcdc_overlay_fb_cleanup(ovl); 2455c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 2456c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (ovl->fb_mem) 2457c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart dma_free_coherent(&pdev->dev, ovl->fb_size, 2458c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->fb_mem, ovl->dma_handle); 2459c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 2460c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 2461b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart for (i = 0; i < ARRAY_SIZE(priv->ch); i++) { 24629a2985e7f943678154f5761dad753f1987c2fdd0Laurent Pinchart struct sh_mobile_lcdc_chan *ch = &priv->ch[i]; 2463b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart 2464e34d0bbb062cc78802d0f0686c939ea1569889a6Laurent Pinchart if (ch->tx_dev) { 2465e34d0bbb062cc78802d0f0686c939ea1569889a6Laurent Pinchart ch->tx_dev->lcdc = NULL; 2466b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart module_put(ch->cfg->tx_dev->dev.driver->owner); 2467e34d0bbb062cc78802d0f0686c939ea1569889a6Laurent Pinchart } 24689a2985e7f943678154f5761dad753f1987c2fdd0Laurent Pinchart 2469a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart sh_mobile_lcdc_channel_fb_cleanup(ch); 2470b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart 2471a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart if (ch->fb_mem) 2472a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart dma_free_coherent(&pdev->dev, ch->fb_size, 2473a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart ch->fb_mem, ch->dma_handle); 2474b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart } 2475b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart 2476b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart for (i = 0; i < ARRAY_SIZE(priv->ch); i++) { 24770c75c4e073a8ec35bfd6c8adcceb2b896f2063e2Laurent Pinchart struct sh_mobile_lcdc_chan *ch = &priv->ch[i]; 24780c75c4e073a8ec35bfd6c8adcceb2b896f2063e2Laurent Pinchart 24790c75c4e073a8ec35bfd6c8adcceb2b896f2063e2Laurent Pinchart if (ch->bl) 24800c75c4e073a8ec35bfd6c8adcceb2b896f2063e2Laurent Pinchart sh_mobile_lcdc_bl_remove(ch->bl); 24810c75c4e073a8ec35bfd6c8adcceb2b896f2063e2Laurent Pinchart mutex_destroy(&ch->open_lock); 2482b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart } 2483b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart 24844774c12aacafc0b8be81b1d159be5a761889e2d7Laurent Pinchart if (priv->dot_clk) { 24854774c12aacafc0b8be81b1d159be5a761889e2d7Laurent Pinchart pm_runtime_disable(&pdev->dev); 2486b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart clk_put(priv->dot_clk); 24874774c12aacafc0b8be81b1d159be5a761889e2d7Laurent Pinchart } 2488b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart 2489b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart if (priv->base) 2490b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart iounmap(priv->base); 2491b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart 2492b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart if (priv->irq) 2493b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart free_irq(priv->irq, priv); 2494b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart kfree(priv); 2495b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart return 0; 2496b4bee692e5d5a3beb5b59ca7967c0a98e3efcc26Laurent Pinchart} 2497cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 2498217e9c4353aa86f0c7eeb4c275bca73ea8b53be1Laurent Pinchartstatic int __devinit sh_mobile_lcdc_check_interface(struct sh_mobile_lcdc_chan *ch) 2499f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart{ 2500b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart int interface_type = ch->cfg->interface_type; 2501f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 2502f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart switch (interface_type) { 2503f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case RGB8: 2504f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case RGB9: 2505f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case RGB12A: 2506f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case RGB12B: 2507f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case RGB16: 2508f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case RGB18: 2509f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case RGB24: 2510f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case SYS8A: 2511f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case SYS8B: 2512f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case SYS8C: 2513f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case SYS8D: 2514f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case SYS9: 2515f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case SYS12: 2516f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case SYS16A: 2517f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case SYS16B: 2518f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case SYS16C: 2519f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case SYS18: 2520f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart case SYS24: 2521f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart break; 2522f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart default: 2523f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart return -EINVAL; 2524f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart } 2525f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 2526f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart /* SUBLCD only supports SYS interface */ 2527f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart if (lcdc_chan_is_sublcd(ch)) { 2528f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart if (!(interface_type & LDMT1R_IFM)) 2529f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart return -EINVAL; 2530f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 2531f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart interface_type &= ~LDMT1R_IFM; 2532f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart } 2533f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 2534f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart ch->ldmt1r_value = interface_type; 2535f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart return 0; 2536f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart} 2537f1f60b5f55099a658a5f79cc453b371a439864e6Laurent Pinchart 25380a7f17aa3d6b693700af2e1cbf8cfdd28e18aebbLaurent Pinchartstatic int __devinit 25390707330b337cec85d7b393303e82f0fad5dc4c00Laurent Pinchartsh_mobile_lcdc_overlay_init(struct sh_mobile_lcdc_overlay *ovl) 2540c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart{ 2541c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart const struct sh_mobile_lcdc_format_info *format; 25420707330b337cec85d7b393303e82f0fad5dc4c00Laurent Pinchart struct device *dev = ovl->channel->lcdc->dev; 2543c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart int ret; 2544c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 2545c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (ovl->cfg->fourcc == 0) 2546c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return 0; 2547c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 2548c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart /* Validate the format. */ 2549c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart format = sh_mobile_format_info(ovl->cfg->fourcc); 2550c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (format == NULL) { 25510707330b337cec85d7b393303e82f0fad5dc4c00Laurent Pinchart dev_err(dev, "Invalid FOURCC %08x\n", ovl->cfg->fourcc); 2552c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return -EINVAL; 2553c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 2554c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 2555c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->enabled = false; 2556c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->mode = LCDC_OVERLAY_BLEND; 2557c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->alpha = 255; 2558c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->rop3 = 0; 2559c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->pos_x = 0; 2560c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->pos_y = 0; 2561c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 2562c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart /* The default Y virtual resolution is twice the panel size to allow for 2563c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * double-buffering. 2564c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart */ 2565c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->format = format; 2566c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->xres = ovl->cfg->max_xres; 2567c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->xres_virtual = ovl->xres; 2568c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->yres = ovl->cfg->max_yres; 2569c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->yres_virtual = ovl->yres * 2; 2570c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 2571c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (!format->yuv) 257216ca21c9a9f64577221c47d8d2f00d13b880aefaLaurent Pinchart ovl->pitch = ovl->xres_virtual * format->bpp / 8; 2573c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart else 257416ca21c9a9f64577221c47d8d2f00d13b880aefaLaurent Pinchart ovl->pitch = ovl->xres_virtual; 2575c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 2576c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart /* Allocate frame buffer memory. */ 2577c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->fb_size = ovl->cfg->max_xres * ovl->cfg->max_yres 2578c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart * format->bpp / 8 * 2; 25790707330b337cec85d7b393303e82f0fad5dc4c00Laurent Pinchart ovl->fb_mem = dma_alloc_coherent(dev, ovl->fb_size, &ovl->dma_handle, 25800707330b337cec85d7b393303e82f0fad5dc4c00Laurent Pinchart GFP_KERNEL); 2581c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (!ovl->fb_mem) { 25820707330b337cec85d7b393303e82f0fad5dc4c00Laurent Pinchart dev_err(dev, "unable to allocate buffer\n"); 2583c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return -ENOMEM; 2584c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 2585c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 2586c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ret = sh_mobile_lcdc_overlay_fb_init(ovl); 2587c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (ret < 0) 2588c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return ret; 2589c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 2590c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart return 0; 2591c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart} 2592c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 2593c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchartstatic int __devinit 25940707330b337cec85d7b393303e82f0fad5dc4c00Laurent Pinchartsh_mobile_lcdc_channel_init(struct sh_mobile_lcdc_chan *ch) 2595cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm{ 2596105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart const struct sh_mobile_lcdc_format_info *format; 2597b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart const struct sh_mobile_lcdc_chan_cfg *cfg = ch->cfg; 25980707330b337cec85d7b393303e82f0fad5dc4c00Laurent Pinchart struct device *dev = ch->lcdc->dev; 25993ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart const struct fb_videomode *max_mode; 26003ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart const struct fb_videomode *mode; 2601a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart unsigned int num_modes; 26023ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart unsigned int max_size; 2603a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart unsigned int i; 26043ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart 2605a67472ad1ae040f073e45048cbc5a01195f2e3f5Laurent Pinchart mutex_init(&ch->open_lock); 2606ecd29947862a9a145c07098499c76c22ed5b8eb3Laurent Pinchart ch->notify = sh_mobile_lcdc_display_notify; 2607a67472ad1ae040f073e45048cbc5a01195f2e3f5Laurent Pinchart 2608105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart /* Validate the format. */ 2609105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart format = sh_mobile_format_info(cfg->fourcc); 2610105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart if (format == NULL) { 26110707330b337cec85d7b393303e82f0fad5dc4c00Laurent Pinchart dev_err(dev, "Invalid FOURCC %08x.\n", cfg->fourcc); 2612105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart return -EINVAL; 2613105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart } 2614105784bbb47cd76f0fc32954b047a13b704fa840Laurent Pinchart 26153ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart /* Iterate through the modes to validate them and find the highest 26163ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart * resolution. 26173ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart */ 26183ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart max_mode = NULL; 26193ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart max_size = 0; 26203ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart 262193ff259846a774ff37dca54792c5a3a6425882c0Laurent Pinchart for (i = 0, mode = cfg->lcd_modes; i < cfg->num_modes; i++, mode++) { 26223ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart unsigned int size = mode->yres * mode->xres; 26233ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart 2624edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart /* NV12/NV21 buffers must have even number of lines */ 2625edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart if ((cfg->fourcc == V4L2_PIX_FMT_NV12 || 2626edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart cfg->fourcc == V4L2_PIX_FMT_NV21) && (mode->yres & 0x1)) { 26270707330b337cec85d7b393303e82f0fad5dc4c00Laurent Pinchart dev_err(dev, "yres must be multiple of 2 for " 26280a7f17aa3d6b693700af2e1cbf8cfdd28e18aebbLaurent Pinchart "YCbCr420 mode.\n"); 26293ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart return -EINVAL; 26303ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart } 26313ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart 26323ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart if (size > max_size) { 26333ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart max_mode = mode; 26343ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart max_size = size; 26353ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart } 26363ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart } 26373ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart 26383ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart if (!max_size) 26393ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart max_size = MAX_XRES * MAX_YRES; 26403ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart else 26410707330b337cec85d7b393303e82f0fad5dc4c00Laurent Pinchart dev_dbg(dev, "Found largest videomode %ux%u\n", 26423ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart max_mode->xres, max_mode->yres); 26433ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart 264493ff259846a774ff37dca54792c5a3a6425882c0Laurent Pinchart if (cfg->lcd_modes == NULL) { 26453ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart mode = &default_720p; 264693ff259846a774ff37dca54792c5a3a6425882c0Laurent Pinchart num_modes = 1; 26473ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart } else { 264893ff259846a774ff37dca54792c5a3a6425882c0Laurent Pinchart mode = cfg->lcd_modes; 264993ff259846a774ff37dca54792c5a3a6425882c0Laurent Pinchart num_modes = cfg->num_modes; 26503ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart } 26513ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart 2652bd5f2c6911c210af52fa4dc4cf504043ff8a4971Laurent Pinchart /* Use the first mode as default. The default Y virtual resolution is 2653bd5f2c6911c210af52fa4dc4cf504043ff8a4971Laurent Pinchart * twice the panel size to allow for double-buffering. 2654bd5f2c6911c210af52fa4dc4cf504043ff8a4971Laurent Pinchart */ 265558f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart ch->format = format; 265658f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart ch->xres = mode->xres; 265758f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart ch->xres_virtual = mode->xres; 265858f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart ch->yres = mode->yres; 265958f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart ch->yres_virtual = mode->yres * 2; 266058f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart 266158f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart if (!format->yuv) { 266258f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart ch->colorspace = V4L2_COLORSPACE_SRGB; 266316ca21c9a9f64577221c47d8d2f00d13b880aefaLaurent Pinchart ch->pitch = ch->xres_virtual * format->bpp / 8; 266458f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart } else { 266558f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart ch->colorspace = V4L2_COLORSPACE_REC709; 266616ca21c9a9f64577221c47d8d2f00d13b880aefaLaurent Pinchart ch->pitch = ch->xres_virtual; 266758f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart } 266858f03d998de08bb15ce50ad875e41bdc281d77ddLaurent Pinchart 2669a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart ch->display.width = cfg->panel_cfg.width; 2670a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart ch->display.height = cfg->panel_cfg.height; 2671a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart ch->display.mode = *mode; 2672a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart 2673a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart /* Allocate frame buffer memory. */ 2674a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart ch->fb_size = max_size * format->bpp / 8 * 2; 26750707330b337cec85d7b393303e82f0fad5dc4c00Laurent Pinchart ch->fb_mem = dma_alloc_coherent(dev, ch->fb_size, &ch->dma_handle, 2676a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart GFP_KERNEL); 2677a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart if (ch->fb_mem == NULL) { 26780707330b337cec85d7b393303e82f0fad5dc4c00Laurent Pinchart dev_err(dev, "unable to allocate buffer\n"); 2679a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart return -ENOMEM; 2680a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart } 26813ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart 268213f80eea562be6cd58b5bdefc224c87cc0d9288dLaurent Pinchart /* Initialize the transmitter device if present. */ 268313f80eea562be6cd58b5bdefc224c87cc0d9288dLaurent Pinchart if (cfg->tx_dev) { 268413f80eea562be6cd58b5bdefc224c87cc0d9288dLaurent Pinchart if (!cfg->tx_dev->dev.driver || 268513f80eea562be6cd58b5bdefc224c87cc0d9288dLaurent Pinchart !try_module_get(cfg->tx_dev->dev.driver->owner)) { 26860707330b337cec85d7b393303e82f0fad5dc4c00Laurent Pinchart dev_warn(dev, "unable to get transmitter device\n"); 268713f80eea562be6cd58b5bdefc224c87cc0d9288dLaurent Pinchart return -EINVAL; 268813f80eea562be6cd58b5bdefc224c87cc0d9288dLaurent Pinchart } 268913f80eea562be6cd58b5bdefc224c87cc0d9288dLaurent Pinchart ch->tx_dev = platform_get_drvdata(cfg->tx_dev); 269013f80eea562be6cd58b5bdefc224c87cc0d9288dLaurent Pinchart ch->tx_dev->lcdc = ch; 269113f80eea562be6cd58b5bdefc224c87cc0d9288dLaurent Pinchart ch->tx_dev->def_mode = *mode; 269213f80eea562be6cd58b5bdefc224c87cc0d9288dLaurent Pinchart } 269313f80eea562be6cd58b5bdefc224c87cc0d9288dLaurent Pinchart 2694a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart return sh_mobile_lcdc_channel_fb_init(ch, mode, num_modes); 26953ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart} 26963ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart 26973ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchartstatic int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) 26983ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart{ 269901ac25b59f08c0bb56dd301f024eabd542205a42Guennadi Liakhovetski struct sh_mobile_lcdc_info *pdata = pdev->dev.platform_data; 27003ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart struct sh_mobile_lcdc_priv *priv; 2701cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm struct resource *res; 27023ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart int num_channels; 2703cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm int error; 27043ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart int i; 2705cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 270601ac25b59f08c0bb56dd301f024eabd542205a42Guennadi Liakhovetski if (!pdata) { 2707cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm dev_err(&pdev->dev, "no platform data defined\n"); 27088bed90557d2600d25e58de30df48b244980164ecGuennadi Liakhovetski return -EINVAL; 2709cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm } 2710cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 2711cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 27128564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm i = platform_get_irq(pdev, 0); 27138564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm if (!res || i < 0) { 27148564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm dev_err(&pdev->dev, "cannot get platform resources\n"); 27158bed90557d2600d25e58de30df48b244980164ecGuennadi Liakhovetski return -ENOENT; 2716cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm } 2717cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 2718cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm priv = kzalloc(sizeof(*priv), GFP_KERNEL); 2719cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm if (!priv) { 2720cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm dev_err(&pdev->dev, "cannot allocate device data\n"); 27218bed90557d2600d25e58de30df48b244980164ecGuennadi Liakhovetski return -ENOMEM; 2722cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm } 2723cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 27244774c12aacafc0b8be81b1d159be5a761889e2d7Laurent Pinchart priv->dev = &pdev->dev; 27254774c12aacafc0b8be81b1d159be5a761889e2d7Laurent Pinchart priv->meram_dev = pdata->meram_dev; 27268bed90557d2600d25e58de30df48b244980164ecGuennadi Liakhovetski platform_set_drvdata(pdev, priv); 27278bed90557d2600d25e58de30df48b244980164ecGuennadi Liakhovetski 2728f8798ccbefc0e4ef7438c080b7ba0410738c8cfaYong Zhang error = request_irq(i, sh_mobile_lcdc_irq, 0, 27297ad33e74857f16f1202cbc5746faf52e88e8b376Kay Sievers dev_name(&pdev->dev), priv); 27308564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm if (error) { 27318564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm dev_err(&pdev->dev, "unable to request irq\n"); 27328564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm goto err1; 27338564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm } 27348564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm 27358564557a03c12adb9c4b76ae1e86db4113a04d13Magnus Damm priv->irq = i; 27365ef6b505d9df45558402bdb823a078840a6a26c4Guennadi Liakhovetski atomic_set(&priv->hw_usecnt, -1); 2737cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 27383ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart for (i = 0, num_channels = 0; i < ARRAY_SIZE(pdata->ch); i++) { 27393ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart struct sh_mobile_lcdc_chan *ch = priv->ch + num_channels; 2740cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 274101ac25b59f08c0bb56dd301f024eabd542205a42Guennadi Liakhovetski ch->lcdc = priv; 2742b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart ch->cfg = &pdata->ch[i]; 2743cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 274401ac25b59f08c0bb56dd301f024eabd542205a42Guennadi Liakhovetski error = sh_mobile_lcdc_check_interface(ch); 2745cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm if (error) { 2746cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm dev_err(&pdev->dev, "unsupported interface type\n"); 2747cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm goto err1; 2748cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm } 274901ac25b59f08c0bb56dd301f024eabd542205a42Guennadi Liakhovetski init_waitqueue_head(&ch->frame_end_wait); 275001ac25b59f08c0bb56dd301f024eabd542205a42Guennadi Liakhovetski init_completion(&ch->vsync_completion); 2751cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 27523b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot /* probe the backlight is there is one defined */ 2753b5ef967df13d4d243a2954c32bdd9181a1ee7382Laurent Pinchart if (ch->cfg->bl_info.max_brightness) 27543b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot ch->bl = sh_mobile_lcdc_bl_probe(&pdev->dev, ch); 27553b0fd9d75598584478d1d3f6551f8a8a9696c34eAlexandre Courbot 2756cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm switch (pdata->ch[i].chan) { 2757cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm case LCDC_CHAN_MAINLCD: 2758ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart ch->enabled = LDCNT2R_ME; 275901ac25b59f08c0bb56dd301f024eabd542205a42Guennadi Liakhovetski ch->reg_offs = lcdc_offs_mainlcd; 27603ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart num_channels++; 2761cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm break; 2762cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm case LCDC_CHAN_SUBLCD: 2763ce1c0b0873bf4e970970a49612105cf6c36d81e3Laurent Pinchart ch->enabled = LDCNT2R_SE; 276401ac25b59f08c0bb56dd301f024eabd542205a42Guennadi Liakhovetski ch->reg_offs = lcdc_offs_sublcd; 27653ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart num_channels++; 2766cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm break; 2767cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm } 2768cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm } 2769cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 27703ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart if (!num_channels) { 2771cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm dev_err(&pdev->dev, "no channels defined\n"); 2772cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm error = -EINVAL; 2773cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm goto err1; 2774cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm } 2775cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 2776edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart /* for dual channel LCDC (MAIN + SUB) force shared format setting */ 27773ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart if (num_channels == 2) 2778edd153a3e4f7346551f98014b3ccf0494219a9d1Laurent Pinchart priv->forced_fourcc = pdata->ch[0].fourcc; 2779417d48274e755e537bae60461558c1f63a4e14deMagnus Damm 2780dba6f385b83d7f19eb1d4df12f422bab945c7f10Guennadi Liakhovetski priv->base = ioremap_nocache(res->start, resource_size(res)); 2781dba6f385b83d7f19eb1d4df12f422bab945c7f10Guennadi Liakhovetski if (!priv->base) 2782dba6f385b83d7f19eb1d4df12f422bab945c7f10Guennadi Liakhovetski goto err1; 2783dba6f385b83d7f19eb1d4df12f422bab945c7f10Guennadi Liakhovetski 27840a7f17aa3d6b693700af2e1cbf8cfdd28e18aebbLaurent Pinchart error = sh_mobile_lcdc_setup_clocks(priv, pdata->clock_source); 2785cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm if (error) { 2786cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm dev_err(&pdev->dev, "unable to setup clocks\n"); 2787cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm goto err1; 2788cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm } 2789cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 27904774c12aacafc0b8be81b1d159be5a761889e2d7Laurent Pinchart /* Enable runtime PM. */ 27914774c12aacafc0b8be81b1d159be5a761889e2d7Laurent Pinchart pm_runtime_enable(&pdev->dev); 27927caa4342ca5b37d2d178b464c16badd4228b3b7bDamian Hobson-Garcia 27933ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart for (i = 0; i < num_channels; i++) { 27940707330b337cec85d7b393303e82f0fad5dc4c00Laurent Pinchart struct sh_mobile_lcdc_chan *ch = &priv->ch[i]; 2795c44f9f76d26c3b5158c65201d30e96393efe2fbdGuennadi Liakhovetski 27960707330b337cec85d7b393303e82f0fad5dc4c00Laurent Pinchart error = sh_mobile_lcdc_channel_init(ch); 2797cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm if (error) 27983ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart goto err1; 2799cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm } 2800cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 2801c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart for (i = 0; i < ARRAY_SIZE(pdata->overlays); i++) { 2802c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_overlay *ovl = &priv->overlays[i]; 2803c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 2804c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->cfg = &pdata->overlays[i]; 2805c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart ovl->channel = &priv->ch[0]; 2806c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 28070707330b337cec85d7b393303e82f0fad5dc4c00Laurent Pinchart error = sh_mobile_lcdc_overlay_init(ovl); 2808c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (error) 2809c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart goto err1; 2810c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 2811c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 2812cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm error = sh_mobile_lcdc_start(priv); 2813cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm if (error) { 2814cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm dev_err(&pdev->dev, "unable to start hardware\n"); 2815cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm goto err1; 2816cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm } 2817cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 28183ce05599907c604a8af9cefe8c5e0702a30d1112Laurent Pinchart for (i = 0; i < num_channels; i++) { 28191c6a307a54668eda556f499c94e75086aaf8f80fPaul Mundt struct sh_mobile_lcdc_chan *ch = priv->ch + i; 28201c6a307a54668eda556f499c94e75086aaf8f80fPaul Mundt 2821a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart error = sh_mobile_lcdc_channel_fb_register(ch); 2822a67f379d3648746be0dab7b616f2fb838ec0fdfbLaurent Pinchart if (error) 2823cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm goto err1; 2824cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm } 2825cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 2826c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart for (i = 0; i < ARRAY_SIZE(pdata->overlays); i++) { 2827c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart struct sh_mobile_lcdc_overlay *ovl = &priv->overlays[i]; 2828c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 2829c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart error = sh_mobile_lcdc_overlay_fb_register(ovl); 2830c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart if (error) 2831c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart goto err1; 2832c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart } 2833c5deac3c9b2284a64326e8799dfe7416bc619c02Laurent Pinchart 28346011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski /* Failure ignored */ 28356011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski priv->notifier.notifier_call = sh_mobile_lcdc_notify; 28366011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski fb_register_client(&priv->notifier); 28376011bdeaa6089d49c02de69f05980da7bad314abGuennadi Liakhovetski 2838cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm return 0; 28398bed90557d2600d25e58de30df48b244980164ecGuennadi Liakhovetskierr1: 2840cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm sh_mobile_lcdc_remove(pdev); 28418bed90557d2600d25e58de30df48b244980164ecGuennadi Liakhovetski 2842cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm return error; 2843cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm} 2844cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 2845cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Dammstatic struct platform_driver sh_mobile_lcdc_driver = { 2846cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm .driver = { 2847cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm .name = "sh_mobile_lcdc_fb", 2848cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm .owner = THIS_MODULE, 28492feb075a33905c2f6ef6be484c75ba6a35f6d12dMagnus Damm .pm = &sh_mobile_lcdc_dev_pm_ops, 2850cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm }, 2851cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm .probe = sh_mobile_lcdc_probe, 2852cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm .remove = sh_mobile_lcdc_remove, 2853cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm}; 2854cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 28554277f2c4667187cbbdd3da3be31ee681bc6b8300Axel Linmodule_platform_driver(sh_mobile_lcdc_driver); 2856cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus Damm 2857cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus DammMODULE_DESCRIPTION("SuperH Mobile LCDC Framebuffer driver"); 2858cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus DammMODULE_AUTHOR("Magnus Damm <damm@opensource.se>"); 2859cfb4f5d1750e05f43902197713c50c29e7dfbc99Magnus DammMODULE_LICENSE("GPL v2"); 2860