1/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. 2 * 3 * This program is free software; you can redistribute it and/or modify 4 * it under the terms of the GNU General Public License version 2 and 5 * only version 2 as published by the Free Software Foundation. 6 * 7 * This program is distributed in the hope that it will be useful, 8 * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 * GNU General Public License for more details. 11 * 12 * You should have received a copy of the GNU General Public License 13 * along with this program; if not, write to the Free Software 14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 15 * 02110-1301, USA. 16 */ 17#include <linux/module.h> 18#include <linux/kernel.h> 19#include <linux/sched.h> 20#include <linux/time.h> 21#include <linux/init.h> 22#include <linux/interrupt.h> 23#include <linux/spinlock.h> 24#include <linux/delay.h> 25#include <mach/hardware.h> 26#include <linux/io.h> 27 28#include <asm/system.h> 29#include <asm/mach-types.h> 30#include <linux/semaphore.h> 31#include <linux/uaccess.h> 32#include <linux/clk.h> 33 34#include "msm_fb.h" 35#include "tvenc.h" 36 37#ifdef CONFIG_FB_MSM_TVOUT_PAL_M 38#define PAL_TV_DIMENSION_WIDTH 720 39#define PAL_TV_DIMENSION_HEIGHT 480 40#else 41#define PAL_TV_DIMENSION_WIDTH 720 42#define PAL_TV_DIMENSION_HEIGHT 576 43#endif 44 45static int pal_on(struct platform_device *pdev) 46{ 47 uint32 reg = 0; 48 int ret = 0; 49 struct msm_fb_data_type *mfd; 50 51 mfd = platform_get_drvdata(pdev); 52 53 if (!mfd) 54 return -ENODEV; 55 56 if (mfd->key != MFD_KEY) 57 return -EINVAL; 58 59 TV_OUT(TV_ENC_CTL, 0); /* disable TV encoder */ 60 61 switch (mfd->panel.id) { 62 case PAL_BDGHIN: 63 /* Cr gain 11, Cb gain C6, y_gain 97 */ 64 TV_OUT(TV_GAIN, 0x0088c1a0); 65 TV_OUT(TV_CGMS, 0x00012345); 66 TV_OUT(TV_TEST_MUX, 0x0); 67 /* PAL Timing */ 68 TV_OUT(TV_SYNC_1, 0x00180097); 69 TV_OUT(TV_SYNC_2, 0x011f06c0); 70 TV_OUT(TV_SYNC_3, 0x0005000a); 71 TV_OUT(TV_SYNC_4, 0x00320271); 72 TV_OUT(TV_SYNC_5, 0x005602f9); 73 TV_OUT(TV_SYNC_6, 0x0005000a); 74 TV_OUT(TV_SYNC_7, 0x0000000f); 75 TV_OUT(TV_BURST_V1, 0x0012026e); 76 TV_OUT(TV_BURST_V2, 0x0011026d); 77 TV_OUT(TV_BURST_V3, 0x00100270); 78 TV_OUT(TV_BURST_V4, 0x0013026f); 79 TV_OUT(TV_BURST_H, 0x00af00ea); 80 TV_OUT(TV_SOL_REQ_ODD, 0x0030026e); 81 TV_OUT(TV_SOL_REQ_EVEN, 0x0031026f); 82 83 reg |= TVENC_CTL_TV_MODE_PAL_BDGHIN; 84 break; 85 case PAL_M: 86 /* Cr gain 11, Cb gain C6, y_gain 97 */ 87 TV_OUT(TV_GAIN, 0x0081b697); 88 TV_OUT(TV_CGMS, 0x000af317); 89 TV_OUT(TV_TEST_MUX, 0x000001c3); 90 TV_OUT(TV_TEST_MODE, 0x00000002); 91 /* PAL Timing */ 92 TV_OUT(TV_SYNC_1, 0x0020009e); 93 TV_OUT(TV_SYNC_2, 0x011306b4); 94 TV_OUT(TV_SYNC_3, 0x0006000c); 95 TV_OUT(TV_SYNC_4, 0x0028020D); 96 TV_OUT(TV_SYNC_5, 0x005e02fb); 97 TV_OUT(TV_SYNC_6, 0x0006000c); 98 TV_OUT(TV_SYNC_7, 0x00000012); 99 TV_OUT(TV_BURST_V1, 0x0012020b); 100 TV_OUT(TV_BURST_V2, 0x0016020c); 101 TV_OUT(TV_BURST_V3, 0x00150209); 102 TV_OUT(TV_BURST_V4, 0x0013020c); 103 TV_OUT(TV_BURST_H, 0x00bf010b); 104 TV_OUT(TV_SOL_REQ_ODD, 0x00280208); 105 TV_OUT(TV_SOL_REQ_EVEN, 0x00290209); 106 107 reg |= TVENC_CTL_TV_MODE_PAL_M; 108 break; 109 case PAL_N: 110 /* Cr gain 11, Cb gain C6, y_gain 97 */ 111 TV_OUT(TV_GAIN, 0x0081b697); 112 TV_OUT(TV_CGMS, 0x000af317); 113 TV_OUT(TV_TEST_MUX, 0x000001c3); 114 TV_OUT(TV_TEST_MODE, 0x00000002); 115 /* PAL Timing */ 116 TV_OUT(TV_SYNC_1, 0x00180097); 117 TV_OUT(TV_SYNC_2, 0x12006c0); 118 TV_OUT(TV_SYNC_3, 0x0005000a); 119 TV_OUT(TV_SYNC_4, 0x00320271); 120 TV_OUT(TV_SYNC_5, 0x005602f9); 121 TV_OUT(TV_SYNC_6, 0x0005000a); 122 TV_OUT(TV_SYNC_7, 0x0000000f); 123 TV_OUT(TV_BURST_V1, 0x0012026e); 124 TV_OUT(TV_BURST_V2, 0x0011026d); 125 TV_OUT(TV_BURST_V3, 0x00100270); 126 TV_OUT(TV_BURST_V4, 0x0013026f); 127 TV_OUT(TV_BURST_H, 0x00af00fa); 128 TV_OUT(TV_SOL_REQ_ODD, 0x0030026e); 129 TV_OUT(TV_SOL_REQ_EVEN, 0x0031026f); 130 131 reg |= TVENC_CTL_TV_MODE_PAL_N; 132 break; 133 134 default: 135 return -ENODEV; 136 } 137 138 reg |= TVENC_CTL_Y_FILTER_EN | 139 TVENC_CTL_CR_FILTER_EN | 140 TVENC_CTL_CB_FILTER_EN | TVENC_CTL_SINX_FILTER_EN; 141#ifdef CONFIG_FB_MSM_TVOUT_SVIDEO 142 reg |= TVENC_CTL_S_VIDEO_EN; 143#endif 144 145 TV_OUT(TV_LEVEL, 0x00000000); /* DC offset to 0. */ 146 TV_OUT(TV_OFFSET, 0x008080f0); 147 148#ifdef CONFIG_FB_MSM_MDP31 149 TV_OUT(TV_DAC_INTF, 0x29); 150#endif 151 TV_OUT(TV_ENC_CTL, reg); 152 153 reg |= TVENC_CTL_ENC_EN; 154 TV_OUT(TV_ENC_CTL, reg); 155 156 return ret; 157} 158 159static int pal_off(struct platform_device *pdev) 160{ 161 TV_OUT(TV_ENC_CTL, 0); /* disable TV encoder */ 162 return 0; 163} 164 165static int __init pal_probe(struct platform_device *pdev) 166{ 167 msm_fb_add_device(pdev); 168 169 return 0; 170} 171 172static struct platform_driver this_driver = { 173 .probe = pal_probe, 174 .driver = { 175 .name = "tv_pal", 176 }, 177}; 178 179static struct msm_fb_panel_data pal_panel_data = { 180 .panel_info.xres = PAL_TV_DIMENSION_WIDTH, 181 .panel_info.yres = PAL_TV_DIMENSION_HEIGHT, 182 .panel_info.type = TV_PANEL, 183 .panel_info.pdest = DISPLAY_1, 184 .panel_info.wait_cycle = 0, 185 .panel_info.bpp = 16, 186 .panel_info.fb_num = 2, 187 .on = pal_on, 188 .off = pal_off, 189}; 190 191static struct platform_device this_device = { 192 .name = "tv_pal", 193 .id = 0, 194 .dev = { 195 .platform_data = &pal_panel_data, 196 } 197}; 198 199static int __init pal_init(void) 200{ 201 int ret; 202 203 ret = platform_driver_register(&this_driver); 204 if (!ret) { 205 ret = platform_device_register(&this_device); 206 if (ret) 207 platform_driver_unregister(&this_driver); 208 } 209 210 return ret; 211} 212 213module_init(pal_init); 214