Commit 9b82f3e61758ed897200f0244b63a77c1791bcba
Committed by
Paul Mackerras
1 parent
486936cd93
Exists in
master
and in
39 other branches
powerpc/ps3: Replace the flip_ctl logic in ps3av and ps3fb by a mutex
Introduce ps3_gpu_mutex to synchronizes GPU-related operations, like: - invoking the L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT command using the lv1_gpu_context_attribute() hypervisor call, - handling the PS3AV_CID_AVB_PARAM packet in the PS3 A/V Settings driver. Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com> Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com> Signed-off-by: Paul Mackerras <paulus@samba.org>
Showing 6 changed files with 14 additions and 38 deletions Inline Diff
arch/powerpc/include/asm/ps3.h
1 | /* | 1 | /* |
2 | * PS3 platform declarations. | 2 | * PS3 platform declarations. |
3 | * | 3 | * |
4 | * Copyright (C) 2006 Sony Computer Entertainment Inc. | 4 | * Copyright (C) 2006 Sony Computer Entertainment Inc. |
5 | * Copyright 2006 Sony Corp. | 5 | * Copyright 2006 Sony Corp. |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License as published by | 8 | * it under the terms of the GNU General Public License as published by |
9 | * the Free Software Foundation; version 2 of the License. | 9 | * the Free Software Foundation; version 2 of the License. |
10 | * | 10 | * |
11 | * This program is distributed in the hope that it will be useful, | 11 | * This program is distributed in the hope that it will be useful, |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | * GNU General Public License for more details. | 14 | * GNU General Public License for more details. |
15 | * | 15 | * |
16 | * You should have received a copy of the GNU General Public License | 16 | * You should have received a copy of the GNU General Public License |
17 | * along with this program; if not, write to the Free Software | 17 | * along with this program; if not, write to the Free Software |
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
19 | */ | 19 | */ |
20 | 20 | ||
21 | #if !defined(_ASM_POWERPC_PS3_H) | 21 | #if !defined(_ASM_POWERPC_PS3_H) |
22 | #define _ASM_POWERPC_PS3_H | 22 | #define _ASM_POWERPC_PS3_H |
23 | 23 | ||
24 | #include <linux/init.h> | 24 | #include <linux/init.h> |
25 | #include <linux/types.h> | 25 | #include <linux/types.h> |
26 | #include <linux/device.h> | 26 | #include <linux/device.h> |
27 | #include "cell-pmu.h" | 27 | #include "cell-pmu.h" |
28 | 28 | ||
29 | union ps3_firmware_version { | 29 | union ps3_firmware_version { |
30 | u64 raw; | 30 | u64 raw; |
31 | struct { | 31 | struct { |
32 | u16 pad; | 32 | u16 pad; |
33 | u16 major; | 33 | u16 major; |
34 | u16 minor; | 34 | u16 minor; |
35 | u16 rev; | 35 | u16 rev; |
36 | }; | 36 | }; |
37 | }; | 37 | }; |
38 | 38 | ||
39 | void ps3_get_firmware_version(union ps3_firmware_version *v); | 39 | void ps3_get_firmware_version(union ps3_firmware_version *v); |
40 | int ps3_compare_firmware_version(u16 major, u16 minor, u16 rev); | 40 | int ps3_compare_firmware_version(u16 major, u16 minor, u16 rev); |
41 | 41 | ||
42 | /* 'Other OS' area */ | 42 | /* 'Other OS' area */ |
43 | 43 | ||
44 | enum ps3_param_av_multi_out { | 44 | enum ps3_param_av_multi_out { |
45 | PS3_PARAM_AV_MULTI_OUT_NTSC = 0, | 45 | PS3_PARAM_AV_MULTI_OUT_NTSC = 0, |
46 | PS3_PARAM_AV_MULTI_OUT_PAL_RGB = 1, | 46 | PS3_PARAM_AV_MULTI_OUT_PAL_RGB = 1, |
47 | PS3_PARAM_AV_MULTI_OUT_PAL_YCBCR = 2, | 47 | PS3_PARAM_AV_MULTI_OUT_PAL_YCBCR = 2, |
48 | PS3_PARAM_AV_MULTI_OUT_SECAM = 3, | 48 | PS3_PARAM_AV_MULTI_OUT_SECAM = 3, |
49 | }; | 49 | }; |
50 | 50 | ||
51 | enum ps3_param_av_multi_out ps3_os_area_get_av_multi_out(void); | 51 | enum ps3_param_av_multi_out ps3_os_area_get_av_multi_out(void); |
52 | 52 | ||
53 | /* dma routines */ | 53 | /* dma routines */ |
54 | 54 | ||
55 | enum ps3_dma_page_size { | 55 | enum ps3_dma_page_size { |
56 | PS3_DMA_4K = 12U, | 56 | PS3_DMA_4K = 12U, |
57 | PS3_DMA_64K = 16U, | 57 | PS3_DMA_64K = 16U, |
58 | PS3_DMA_1M = 20U, | 58 | PS3_DMA_1M = 20U, |
59 | PS3_DMA_16M = 24U, | 59 | PS3_DMA_16M = 24U, |
60 | }; | 60 | }; |
61 | 61 | ||
62 | enum ps3_dma_region_type { | 62 | enum ps3_dma_region_type { |
63 | PS3_DMA_OTHER = 0, | 63 | PS3_DMA_OTHER = 0, |
64 | PS3_DMA_INTERNAL = 2, | 64 | PS3_DMA_INTERNAL = 2, |
65 | }; | 65 | }; |
66 | 66 | ||
67 | struct ps3_dma_region_ops; | 67 | struct ps3_dma_region_ops; |
68 | 68 | ||
69 | /** | 69 | /** |
70 | * struct ps3_dma_region - A per device dma state variables structure | 70 | * struct ps3_dma_region - A per device dma state variables structure |
71 | * @did: The HV device id. | 71 | * @did: The HV device id. |
72 | * @page_size: The ioc pagesize. | 72 | * @page_size: The ioc pagesize. |
73 | * @region_type: The HV region type. | 73 | * @region_type: The HV region type. |
74 | * @bus_addr: The 'translated' bus address of the region. | 74 | * @bus_addr: The 'translated' bus address of the region. |
75 | * @len: The length in bytes of the region. | 75 | * @len: The length in bytes of the region. |
76 | * @offset: The offset from the start of memory of the region. | 76 | * @offset: The offset from the start of memory of the region. |
77 | * @ioid: The IOID of the device who owns this region | 77 | * @ioid: The IOID of the device who owns this region |
78 | * @chunk_list: Opaque variable used by the ioc page manager. | 78 | * @chunk_list: Opaque variable used by the ioc page manager. |
79 | * @region_ops: struct ps3_dma_region_ops - dma region operations | 79 | * @region_ops: struct ps3_dma_region_ops - dma region operations |
80 | */ | 80 | */ |
81 | 81 | ||
82 | struct ps3_dma_region { | 82 | struct ps3_dma_region { |
83 | struct ps3_system_bus_device *dev; | 83 | struct ps3_system_bus_device *dev; |
84 | /* device variables */ | 84 | /* device variables */ |
85 | const struct ps3_dma_region_ops *region_ops; | 85 | const struct ps3_dma_region_ops *region_ops; |
86 | unsigned char ioid; | 86 | unsigned char ioid; |
87 | enum ps3_dma_page_size page_size; | 87 | enum ps3_dma_page_size page_size; |
88 | enum ps3_dma_region_type region_type; | 88 | enum ps3_dma_region_type region_type; |
89 | unsigned long len; | 89 | unsigned long len; |
90 | unsigned long offset; | 90 | unsigned long offset; |
91 | 91 | ||
92 | /* driver variables (set by ps3_dma_region_create) */ | 92 | /* driver variables (set by ps3_dma_region_create) */ |
93 | unsigned long bus_addr; | 93 | unsigned long bus_addr; |
94 | struct { | 94 | struct { |
95 | spinlock_t lock; | 95 | spinlock_t lock; |
96 | struct list_head head; | 96 | struct list_head head; |
97 | } chunk_list; | 97 | } chunk_list; |
98 | }; | 98 | }; |
99 | 99 | ||
100 | struct ps3_dma_region_ops { | 100 | struct ps3_dma_region_ops { |
101 | int (*create)(struct ps3_dma_region *); | 101 | int (*create)(struct ps3_dma_region *); |
102 | int (*free)(struct ps3_dma_region *); | 102 | int (*free)(struct ps3_dma_region *); |
103 | int (*map)(struct ps3_dma_region *, | 103 | int (*map)(struct ps3_dma_region *, |
104 | unsigned long virt_addr, | 104 | unsigned long virt_addr, |
105 | unsigned long len, | 105 | unsigned long len, |
106 | unsigned long *bus_addr, | 106 | unsigned long *bus_addr, |
107 | u64 iopte_pp); | 107 | u64 iopte_pp); |
108 | int (*unmap)(struct ps3_dma_region *, | 108 | int (*unmap)(struct ps3_dma_region *, |
109 | unsigned long bus_addr, | 109 | unsigned long bus_addr, |
110 | unsigned long len); | 110 | unsigned long len); |
111 | }; | 111 | }; |
112 | /** | 112 | /** |
113 | * struct ps3_dma_region_init - Helper to initialize structure variables | 113 | * struct ps3_dma_region_init - Helper to initialize structure variables |
114 | * | 114 | * |
115 | * Helper to properly initialize variables prior to calling | 115 | * Helper to properly initialize variables prior to calling |
116 | * ps3_system_bus_device_register. | 116 | * ps3_system_bus_device_register. |
117 | */ | 117 | */ |
118 | 118 | ||
119 | struct ps3_system_bus_device; | 119 | struct ps3_system_bus_device; |
120 | 120 | ||
121 | int ps3_dma_region_init(struct ps3_system_bus_device *dev, | 121 | int ps3_dma_region_init(struct ps3_system_bus_device *dev, |
122 | struct ps3_dma_region *r, enum ps3_dma_page_size page_size, | 122 | struct ps3_dma_region *r, enum ps3_dma_page_size page_size, |
123 | enum ps3_dma_region_type region_type, void *addr, unsigned long len); | 123 | enum ps3_dma_region_type region_type, void *addr, unsigned long len); |
124 | int ps3_dma_region_create(struct ps3_dma_region *r); | 124 | int ps3_dma_region_create(struct ps3_dma_region *r); |
125 | int ps3_dma_region_free(struct ps3_dma_region *r); | 125 | int ps3_dma_region_free(struct ps3_dma_region *r); |
126 | int ps3_dma_map(struct ps3_dma_region *r, unsigned long virt_addr, | 126 | int ps3_dma_map(struct ps3_dma_region *r, unsigned long virt_addr, |
127 | unsigned long len, unsigned long *bus_addr, | 127 | unsigned long len, unsigned long *bus_addr, |
128 | u64 iopte_pp); | 128 | u64 iopte_pp); |
129 | int ps3_dma_unmap(struct ps3_dma_region *r, unsigned long bus_addr, | 129 | int ps3_dma_unmap(struct ps3_dma_region *r, unsigned long bus_addr, |
130 | unsigned long len); | 130 | unsigned long len); |
131 | 131 | ||
132 | /* mmio routines */ | 132 | /* mmio routines */ |
133 | 133 | ||
134 | enum ps3_mmio_page_size { | 134 | enum ps3_mmio_page_size { |
135 | PS3_MMIO_4K = 12U, | 135 | PS3_MMIO_4K = 12U, |
136 | PS3_MMIO_64K = 16U | 136 | PS3_MMIO_64K = 16U |
137 | }; | 137 | }; |
138 | 138 | ||
139 | struct ps3_mmio_region_ops; | 139 | struct ps3_mmio_region_ops; |
140 | /** | 140 | /** |
141 | * struct ps3_mmio_region - a per device mmio state variables structure | 141 | * struct ps3_mmio_region - a per device mmio state variables structure |
142 | * | 142 | * |
143 | * Current systems can be supported with a single region per device. | 143 | * Current systems can be supported with a single region per device. |
144 | */ | 144 | */ |
145 | 145 | ||
146 | struct ps3_mmio_region { | 146 | struct ps3_mmio_region { |
147 | struct ps3_system_bus_device *dev; | 147 | struct ps3_system_bus_device *dev; |
148 | const struct ps3_mmio_region_ops *mmio_ops; | 148 | const struct ps3_mmio_region_ops *mmio_ops; |
149 | unsigned long bus_addr; | 149 | unsigned long bus_addr; |
150 | unsigned long len; | 150 | unsigned long len; |
151 | enum ps3_mmio_page_size page_size; | 151 | enum ps3_mmio_page_size page_size; |
152 | unsigned long lpar_addr; | 152 | unsigned long lpar_addr; |
153 | }; | 153 | }; |
154 | 154 | ||
155 | struct ps3_mmio_region_ops { | 155 | struct ps3_mmio_region_ops { |
156 | int (*create)(struct ps3_mmio_region *); | 156 | int (*create)(struct ps3_mmio_region *); |
157 | int (*free)(struct ps3_mmio_region *); | 157 | int (*free)(struct ps3_mmio_region *); |
158 | }; | 158 | }; |
159 | /** | 159 | /** |
160 | * struct ps3_mmio_region_init - Helper to initialize structure variables | 160 | * struct ps3_mmio_region_init - Helper to initialize structure variables |
161 | * | 161 | * |
162 | * Helper to properly initialize variables prior to calling | 162 | * Helper to properly initialize variables prior to calling |
163 | * ps3_system_bus_device_register. | 163 | * ps3_system_bus_device_register. |
164 | */ | 164 | */ |
165 | 165 | ||
166 | int ps3_mmio_region_init(struct ps3_system_bus_device *dev, | 166 | int ps3_mmio_region_init(struct ps3_system_bus_device *dev, |
167 | struct ps3_mmio_region *r, unsigned long bus_addr, unsigned long len, | 167 | struct ps3_mmio_region *r, unsigned long bus_addr, unsigned long len, |
168 | enum ps3_mmio_page_size page_size); | 168 | enum ps3_mmio_page_size page_size); |
169 | int ps3_mmio_region_create(struct ps3_mmio_region *r); | 169 | int ps3_mmio_region_create(struct ps3_mmio_region *r); |
170 | int ps3_free_mmio_region(struct ps3_mmio_region *r); | 170 | int ps3_free_mmio_region(struct ps3_mmio_region *r); |
171 | unsigned long ps3_mm_phys_to_lpar(unsigned long phys_addr); | 171 | unsigned long ps3_mm_phys_to_lpar(unsigned long phys_addr); |
172 | 172 | ||
173 | /* inrerrupt routines */ | 173 | /* inrerrupt routines */ |
174 | 174 | ||
175 | enum ps3_cpu_binding { | 175 | enum ps3_cpu_binding { |
176 | PS3_BINDING_CPU_ANY = -1, | 176 | PS3_BINDING_CPU_ANY = -1, |
177 | PS3_BINDING_CPU_0 = 0, | 177 | PS3_BINDING_CPU_0 = 0, |
178 | PS3_BINDING_CPU_1 = 1, | 178 | PS3_BINDING_CPU_1 = 1, |
179 | }; | 179 | }; |
180 | 180 | ||
181 | int ps3_irq_plug_setup(enum ps3_cpu_binding cpu, unsigned long outlet, | 181 | int ps3_irq_plug_setup(enum ps3_cpu_binding cpu, unsigned long outlet, |
182 | unsigned int *virq); | 182 | unsigned int *virq); |
183 | int ps3_irq_plug_destroy(unsigned int virq); | 183 | int ps3_irq_plug_destroy(unsigned int virq); |
184 | int ps3_event_receive_port_setup(enum ps3_cpu_binding cpu, unsigned int *virq); | 184 | int ps3_event_receive_port_setup(enum ps3_cpu_binding cpu, unsigned int *virq); |
185 | int ps3_event_receive_port_destroy(unsigned int virq); | 185 | int ps3_event_receive_port_destroy(unsigned int virq); |
186 | int ps3_send_event_locally(unsigned int virq); | 186 | int ps3_send_event_locally(unsigned int virq); |
187 | 187 | ||
188 | int ps3_io_irq_setup(enum ps3_cpu_binding cpu, unsigned int interrupt_id, | 188 | int ps3_io_irq_setup(enum ps3_cpu_binding cpu, unsigned int interrupt_id, |
189 | unsigned int *virq); | 189 | unsigned int *virq); |
190 | int ps3_io_irq_destroy(unsigned int virq); | 190 | int ps3_io_irq_destroy(unsigned int virq); |
191 | int ps3_vuart_irq_setup(enum ps3_cpu_binding cpu, void* virt_addr_bmp, | 191 | int ps3_vuart_irq_setup(enum ps3_cpu_binding cpu, void* virt_addr_bmp, |
192 | unsigned int *virq); | 192 | unsigned int *virq); |
193 | int ps3_vuart_irq_destroy(unsigned int virq); | 193 | int ps3_vuart_irq_destroy(unsigned int virq); |
194 | int ps3_spe_irq_setup(enum ps3_cpu_binding cpu, unsigned long spe_id, | 194 | int ps3_spe_irq_setup(enum ps3_cpu_binding cpu, unsigned long spe_id, |
195 | unsigned int class, unsigned int *virq); | 195 | unsigned int class, unsigned int *virq); |
196 | int ps3_spe_irq_destroy(unsigned int virq); | 196 | int ps3_spe_irq_destroy(unsigned int virq); |
197 | 197 | ||
198 | int ps3_sb_event_receive_port_setup(struct ps3_system_bus_device *dev, | 198 | int ps3_sb_event_receive_port_setup(struct ps3_system_bus_device *dev, |
199 | enum ps3_cpu_binding cpu, unsigned int *virq); | 199 | enum ps3_cpu_binding cpu, unsigned int *virq); |
200 | int ps3_sb_event_receive_port_destroy(struct ps3_system_bus_device *dev, | 200 | int ps3_sb_event_receive_port_destroy(struct ps3_system_bus_device *dev, |
201 | unsigned int virq); | 201 | unsigned int virq); |
202 | 202 | ||
203 | /* lv1 result codes */ | 203 | /* lv1 result codes */ |
204 | 204 | ||
205 | enum lv1_result { | 205 | enum lv1_result { |
206 | LV1_SUCCESS = 0, | 206 | LV1_SUCCESS = 0, |
207 | /* not used -1 */ | 207 | /* not used -1 */ |
208 | LV1_RESOURCE_SHORTAGE = -2, | 208 | LV1_RESOURCE_SHORTAGE = -2, |
209 | LV1_NO_PRIVILEGE = -3, | 209 | LV1_NO_PRIVILEGE = -3, |
210 | LV1_DENIED_BY_POLICY = -4, | 210 | LV1_DENIED_BY_POLICY = -4, |
211 | LV1_ACCESS_VIOLATION = -5, | 211 | LV1_ACCESS_VIOLATION = -5, |
212 | LV1_NO_ENTRY = -6, | 212 | LV1_NO_ENTRY = -6, |
213 | LV1_DUPLICATE_ENTRY = -7, | 213 | LV1_DUPLICATE_ENTRY = -7, |
214 | LV1_TYPE_MISMATCH = -8, | 214 | LV1_TYPE_MISMATCH = -8, |
215 | LV1_BUSY = -9, | 215 | LV1_BUSY = -9, |
216 | LV1_EMPTY = -10, | 216 | LV1_EMPTY = -10, |
217 | LV1_WRONG_STATE = -11, | 217 | LV1_WRONG_STATE = -11, |
218 | /* not used -12 */ | 218 | /* not used -12 */ |
219 | LV1_NO_MATCH = -13, | 219 | LV1_NO_MATCH = -13, |
220 | LV1_ALREADY_CONNECTED = -14, | 220 | LV1_ALREADY_CONNECTED = -14, |
221 | LV1_UNSUPPORTED_PARAMETER_VALUE = -15, | 221 | LV1_UNSUPPORTED_PARAMETER_VALUE = -15, |
222 | LV1_CONDITION_NOT_SATISFIED = -16, | 222 | LV1_CONDITION_NOT_SATISFIED = -16, |
223 | LV1_ILLEGAL_PARAMETER_VALUE = -17, | 223 | LV1_ILLEGAL_PARAMETER_VALUE = -17, |
224 | LV1_BAD_OPTION = -18, | 224 | LV1_BAD_OPTION = -18, |
225 | LV1_IMPLEMENTATION_LIMITATION = -19, | 225 | LV1_IMPLEMENTATION_LIMITATION = -19, |
226 | LV1_NOT_IMPLEMENTED = -20, | 226 | LV1_NOT_IMPLEMENTED = -20, |
227 | LV1_INVALID_CLASS_ID = -21, | 227 | LV1_INVALID_CLASS_ID = -21, |
228 | LV1_CONSTRAINT_NOT_SATISFIED = -22, | 228 | LV1_CONSTRAINT_NOT_SATISFIED = -22, |
229 | LV1_ALIGNMENT_ERROR = -23, | 229 | LV1_ALIGNMENT_ERROR = -23, |
230 | LV1_HARDWARE_ERROR = -24, | 230 | LV1_HARDWARE_ERROR = -24, |
231 | LV1_INVALID_DATA_FORMAT = -25, | 231 | LV1_INVALID_DATA_FORMAT = -25, |
232 | LV1_INVALID_OPERATION = -26, | 232 | LV1_INVALID_OPERATION = -26, |
233 | LV1_INTERNAL_ERROR = -32768, | 233 | LV1_INTERNAL_ERROR = -32768, |
234 | }; | 234 | }; |
235 | 235 | ||
236 | static inline const char* ps3_result(int result) | 236 | static inline const char* ps3_result(int result) |
237 | { | 237 | { |
238 | #if defined(DEBUG) | 238 | #if defined(DEBUG) |
239 | switch (result) { | 239 | switch (result) { |
240 | case LV1_SUCCESS: | 240 | case LV1_SUCCESS: |
241 | return "LV1_SUCCESS (0)"; | 241 | return "LV1_SUCCESS (0)"; |
242 | case -1: | 242 | case -1: |
243 | return "** unknown result ** (-1)"; | 243 | return "** unknown result ** (-1)"; |
244 | case LV1_RESOURCE_SHORTAGE: | 244 | case LV1_RESOURCE_SHORTAGE: |
245 | return "LV1_RESOURCE_SHORTAGE (-2)"; | 245 | return "LV1_RESOURCE_SHORTAGE (-2)"; |
246 | case LV1_NO_PRIVILEGE: | 246 | case LV1_NO_PRIVILEGE: |
247 | return "LV1_NO_PRIVILEGE (-3)"; | 247 | return "LV1_NO_PRIVILEGE (-3)"; |
248 | case LV1_DENIED_BY_POLICY: | 248 | case LV1_DENIED_BY_POLICY: |
249 | return "LV1_DENIED_BY_POLICY (-4)"; | 249 | return "LV1_DENIED_BY_POLICY (-4)"; |
250 | case LV1_ACCESS_VIOLATION: | 250 | case LV1_ACCESS_VIOLATION: |
251 | return "LV1_ACCESS_VIOLATION (-5)"; | 251 | return "LV1_ACCESS_VIOLATION (-5)"; |
252 | case LV1_NO_ENTRY: | 252 | case LV1_NO_ENTRY: |
253 | return "LV1_NO_ENTRY (-6)"; | 253 | return "LV1_NO_ENTRY (-6)"; |
254 | case LV1_DUPLICATE_ENTRY: | 254 | case LV1_DUPLICATE_ENTRY: |
255 | return "LV1_DUPLICATE_ENTRY (-7)"; | 255 | return "LV1_DUPLICATE_ENTRY (-7)"; |
256 | case LV1_TYPE_MISMATCH: | 256 | case LV1_TYPE_MISMATCH: |
257 | return "LV1_TYPE_MISMATCH (-8)"; | 257 | return "LV1_TYPE_MISMATCH (-8)"; |
258 | case LV1_BUSY: | 258 | case LV1_BUSY: |
259 | return "LV1_BUSY (-9)"; | 259 | return "LV1_BUSY (-9)"; |
260 | case LV1_EMPTY: | 260 | case LV1_EMPTY: |
261 | return "LV1_EMPTY (-10)"; | 261 | return "LV1_EMPTY (-10)"; |
262 | case LV1_WRONG_STATE: | 262 | case LV1_WRONG_STATE: |
263 | return "LV1_WRONG_STATE (-11)"; | 263 | return "LV1_WRONG_STATE (-11)"; |
264 | case -12: | 264 | case -12: |
265 | return "** unknown result ** (-12)"; | 265 | return "** unknown result ** (-12)"; |
266 | case LV1_NO_MATCH: | 266 | case LV1_NO_MATCH: |
267 | return "LV1_NO_MATCH (-13)"; | 267 | return "LV1_NO_MATCH (-13)"; |
268 | case LV1_ALREADY_CONNECTED: | 268 | case LV1_ALREADY_CONNECTED: |
269 | return "LV1_ALREADY_CONNECTED (-14)"; | 269 | return "LV1_ALREADY_CONNECTED (-14)"; |
270 | case LV1_UNSUPPORTED_PARAMETER_VALUE: | 270 | case LV1_UNSUPPORTED_PARAMETER_VALUE: |
271 | return "LV1_UNSUPPORTED_PARAMETER_VALUE (-15)"; | 271 | return "LV1_UNSUPPORTED_PARAMETER_VALUE (-15)"; |
272 | case LV1_CONDITION_NOT_SATISFIED: | 272 | case LV1_CONDITION_NOT_SATISFIED: |
273 | return "LV1_CONDITION_NOT_SATISFIED (-16)"; | 273 | return "LV1_CONDITION_NOT_SATISFIED (-16)"; |
274 | case LV1_ILLEGAL_PARAMETER_VALUE: | 274 | case LV1_ILLEGAL_PARAMETER_VALUE: |
275 | return "LV1_ILLEGAL_PARAMETER_VALUE (-17)"; | 275 | return "LV1_ILLEGAL_PARAMETER_VALUE (-17)"; |
276 | case LV1_BAD_OPTION: | 276 | case LV1_BAD_OPTION: |
277 | return "LV1_BAD_OPTION (-18)"; | 277 | return "LV1_BAD_OPTION (-18)"; |
278 | case LV1_IMPLEMENTATION_LIMITATION: | 278 | case LV1_IMPLEMENTATION_LIMITATION: |
279 | return "LV1_IMPLEMENTATION_LIMITATION (-19)"; | 279 | return "LV1_IMPLEMENTATION_LIMITATION (-19)"; |
280 | case LV1_NOT_IMPLEMENTED: | 280 | case LV1_NOT_IMPLEMENTED: |
281 | return "LV1_NOT_IMPLEMENTED (-20)"; | 281 | return "LV1_NOT_IMPLEMENTED (-20)"; |
282 | case LV1_INVALID_CLASS_ID: | 282 | case LV1_INVALID_CLASS_ID: |
283 | return "LV1_INVALID_CLASS_ID (-21)"; | 283 | return "LV1_INVALID_CLASS_ID (-21)"; |
284 | case LV1_CONSTRAINT_NOT_SATISFIED: | 284 | case LV1_CONSTRAINT_NOT_SATISFIED: |
285 | return "LV1_CONSTRAINT_NOT_SATISFIED (-22)"; | 285 | return "LV1_CONSTRAINT_NOT_SATISFIED (-22)"; |
286 | case LV1_ALIGNMENT_ERROR: | 286 | case LV1_ALIGNMENT_ERROR: |
287 | return "LV1_ALIGNMENT_ERROR (-23)"; | 287 | return "LV1_ALIGNMENT_ERROR (-23)"; |
288 | case LV1_HARDWARE_ERROR: | 288 | case LV1_HARDWARE_ERROR: |
289 | return "LV1_HARDWARE_ERROR (-24)"; | 289 | return "LV1_HARDWARE_ERROR (-24)"; |
290 | case LV1_INVALID_DATA_FORMAT: | 290 | case LV1_INVALID_DATA_FORMAT: |
291 | return "LV1_INVALID_DATA_FORMAT (-25)"; | 291 | return "LV1_INVALID_DATA_FORMAT (-25)"; |
292 | case LV1_INVALID_OPERATION: | 292 | case LV1_INVALID_OPERATION: |
293 | return "LV1_INVALID_OPERATION (-26)"; | 293 | return "LV1_INVALID_OPERATION (-26)"; |
294 | case LV1_INTERNAL_ERROR: | 294 | case LV1_INTERNAL_ERROR: |
295 | return "LV1_INTERNAL_ERROR (-32768)"; | 295 | return "LV1_INTERNAL_ERROR (-32768)"; |
296 | default: | 296 | default: |
297 | BUG(); | 297 | BUG(); |
298 | return "** unknown result **"; | 298 | return "** unknown result **"; |
299 | }; | 299 | }; |
300 | #else | 300 | #else |
301 | return ""; | 301 | return ""; |
302 | #endif | 302 | #endif |
303 | } | 303 | } |
304 | 304 | ||
305 | /* system bus routines */ | 305 | /* system bus routines */ |
306 | 306 | ||
307 | enum ps3_match_id { | 307 | enum ps3_match_id { |
308 | PS3_MATCH_ID_EHCI = 1, | 308 | PS3_MATCH_ID_EHCI = 1, |
309 | PS3_MATCH_ID_OHCI = 2, | 309 | PS3_MATCH_ID_OHCI = 2, |
310 | PS3_MATCH_ID_GELIC = 3, | 310 | PS3_MATCH_ID_GELIC = 3, |
311 | PS3_MATCH_ID_AV_SETTINGS = 4, | 311 | PS3_MATCH_ID_AV_SETTINGS = 4, |
312 | PS3_MATCH_ID_SYSTEM_MANAGER = 5, | 312 | PS3_MATCH_ID_SYSTEM_MANAGER = 5, |
313 | PS3_MATCH_ID_STOR_DISK = 6, | 313 | PS3_MATCH_ID_STOR_DISK = 6, |
314 | PS3_MATCH_ID_STOR_ROM = 7, | 314 | PS3_MATCH_ID_STOR_ROM = 7, |
315 | PS3_MATCH_ID_STOR_FLASH = 8, | 315 | PS3_MATCH_ID_STOR_FLASH = 8, |
316 | PS3_MATCH_ID_SOUND = 9, | 316 | PS3_MATCH_ID_SOUND = 9, |
317 | PS3_MATCH_ID_GRAPHICS = 10, | 317 | PS3_MATCH_ID_GRAPHICS = 10, |
318 | PS3_MATCH_ID_LPM = 11, | 318 | PS3_MATCH_ID_LPM = 11, |
319 | }; | 319 | }; |
320 | 320 | ||
321 | #define PS3_MODULE_ALIAS_EHCI "ps3:1" | 321 | #define PS3_MODULE_ALIAS_EHCI "ps3:1" |
322 | #define PS3_MODULE_ALIAS_OHCI "ps3:2" | 322 | #define PS3_MODULE_ALIAS_OHCI "ps3:2" |
323 | #define PS3_MODULE_ALIAS_GELIC "ps3:3" | 323 | #define PS3_MODULE_ALIAS_GELIC "ps3:3" |
324 | #define PS3_MODULE_ALIAS_AV_SETTINGS "ps3:4" | 324 | #define PS3_MODULE_ALIAS_AV_SETTINGS "ps3:4" |
325 | #define PS3_MODULE_ALIAS_SYSTEM_MANAGER "ps3:5" | 325 | #define PS3_MODULE_ALIAS_SYSTEM_MANAGER "ps3:5" |
326 | #define PS3_MODULE_ALIAS_STOR_DISK "ps3:6" | 326 | #define PS3_MODULE_ALIAS_STOR_DISK "ps3:6" |
327 | #define PS3_MODULE_ALIAS_STOR_ROM "ps3:7" | 327 | #define PS3_MODULE_ALIAS_STOR_ROM "ps3:7" |
328 | #define PS3_MODULE_ALIAS_STOR_FLASH "ps3:8" | 328 | #define PS3_MODULE_ALIAS_STOR_FLASH "ps3:8" |
329 | #define PS3_MODULE_ALIAS_SOUND "ps3:9" | 329 | #define PS3_MODULE_ALIAS_SOUND "ps3:9" |
330 | #define PS3_MODULE_ALIAS_GRAPHICS "ps3:10" | 330 | #define PS3_MODULE_ALIAS_GRAPHICS "ps3:10" |
331 | #define PS3_MODULE_ALIAS_LPM "ps3:11" | 331 | #define PS3_MODULE_ALIAS_LPM "ps3:11" |
332 | 332 | ||
333 | enum ps3_system_bus_device_type { | 333 | enum ps3_system_bus_device_type { |
334 | PS3_DEVICE_TYPE_IOC0 = 1, | 334 | PS3_DEVICE_TYPE_IOC0 = 1, |
335 | PS3_DEVICE_TYPE_SB, | 335 | PS3_DEVICE_TYPE_SB, |
336 | PS3_DEVICE_TYPE_VUART, | 336 | PS3_DEVICE_TYPE_VUART, |
337 | PS3_DEVICE_TYPE_LPM, | 337 | PS3_DEVICE_TYPE_LPM, |
338 | }; | 338 | }; |
339 | 339 | ||
340 | enum ps3_match_sub_id { | 340 | enum ps3_match_sub_id { |
341 | /* for PS3_MATCH_ID_GRAPHICS */ | 341 | /* for PS3_MATCH_ID_GRAPHICS */ |
342 | PS3_MATCH_SUB_ID_FB = 1, | 342 | PS3_MATCH_SUB_ID_FB = 1, |
343 | }; | 343 | }; |
344 | 344 | ||
345 | /** | 345 | /** |
346 | * struct ps3_system_bus_device - a device on the system bus | 346 | * struct ps3_system_bus_device - a device on the system bus |
347 | */ | 347 | */ |
348 | 348 | ||
349 | struct ps3_system_bus_device { | 349 | struct ps3_system_bus_device { |
350 | enum ps3_match_id match_id; | 350 | enum ps3_match_id match_id; |
351 | enum ps3_match_sub_id match_sub_id; | 351 | enum ps3_match_sub_id match_sub_id; |
352 | enum ps3_system_bus_device_type dev_type; | 352 | enum ps3_system_bus_device_type dev_type; |
353 | 353 | ||
354 | u64 bus_id; /* SB */ | 354 | u64 bus_id; /* SB */ |
355 | u64 dev_id; /* SB */ | 355 | u64 dev_id; /* SB */ |
356 | unsigned int interrupt_id; /* SB */ | 356 | unsigned int interrupt_id; /* SB */ |
357 | struct ps3_dma_region *d_region; /* SB, IOC0 */ | 357 | struct ps3_dma_region *d_region; /* SB, IOC0 */ |
358 | struct ps3_mmio_region *m_region; /* SB, IOC0*/ | 358 | struct ps3_mmio_region *m_region; /* SB, IOC0*/ |
359 | unsigned int port_number; /* VUART */ | 359 | unsigned int port_number; /* VUART */ |
360 | struct { /* LPM */ | 360 | struct { /* LPM */ |
361 | u64 node_id; | 361 | u64 node_id; |
362 | u64 pu_id; | 362 | u64 pu_id; |
363 | u64 rights; | 363 | u64 rights; |
364 | } lpm; | 364 | } lpm; |
365 | 365 | ||
366 | /* struct iommu_table *iommu_table; -- waiting for BenH's cleanups */ | 366 | /* struct iommu_table *iommu_table; -- waiting for BenH's cleanups */ |
367 | struct device core; | 367 | struct device core; |
368 | void *driver_priv; /* private driver variables */ | 368 | void *driver_priv; /* private driver variables */ |
369 | }; | 369 | }; |
370 | 370 | ||
371 | int ps3_open_hv_device(struct ps3_system_bus_device *dev); | 371 | int ps3_open_hv_device(struct ps3_system_bus_device *dev); |
372 | int ps3_close_hv_device(struct ps3_system_bus_device *dev); | 372 | int ps3_close_hv_device(struct ps3_system_bus_device *dev); |
373 | 373 | ||
374 | /** | 374 | /** |
375 | * struct ps3_system_bus_driver - a driver for a device on the system bus | 375 | * struct ps3_system_bus_driver - a driver for a device on the system bus |
376 | */ | 376 | */ |
377 | 377 | ||
378 | struct ps3_system_bus_driver { | 378 | struct ps3_system_bus_driver { |
379 | enum ps3_match_id match_id; | 379 | enum ps3_match_id match_id; |
380 | enum ps3_match_sub_id match_sub_id; | 380 | enum ps3_match_sub_id match_sub_id; |
381 | struct device_driver core; | 381 | struct device_driver core; |
382 | int (*probe)(struct ps3_system_bus_device *); | 382 | int (*probe)(struct ps3_system_bus_device *); |
383 | int (*remove)(struct ps3_system_bus_device *); | 383 | int (*remove)(struct ps3_system_bus_device *); |
384 | int (*shutdown)(struct ps3_system_bus_device *); | 384 | int (*shutdown)(struct ps3_system_bus_device *); |
385 | /* int (*suspend)(struct ps3_system_bus_device *, pm_message_t); */ | 385 | /* int (*suspend)(struct ps3_system_bus_device *, pm_message_t); */ |
386 | /* int (*resume)(struct ps3_system_bus_device *); */ | 386 | /* int (*resume)(struct ps3_system_bus_device *); */ |
387 | }; | 387 | }; |
388 | 388 | ||
389 | int ps3_system_bus_device_register(struct ps3_system_bus_device *dev); | 389 | int ps3_system_bus_device_register(struct ps3_system_bus_device *dev); |
390 | int ps3_system_bus_driver_register(struct ps3_system_bus_driver *drv); | 390 | int ps3_system_bus_driver_register(struct ps3_system_bus_driver *drv); |
391 | void ps3_system_bus_driver_unregister(struct ps3_system_bus_driver *drv); | 391 | void ps3_system_bus_driver_unregister(struct ps3_system_bus_driver *drv); |
392 | 392 | ||
393 | static inline struct ps3_system_bus_driver *ps3_drv_to_system_bus_drv( | 393 | static inline struct ps3_system_bus_driver *ps3_drv_to_system_bus_drv( |
394 | struct device_driver *_drv) | 394 | struct device_driver *_drv) |
395 | { | 395 | { |
396 | return container_of(_drv, struct ps3_system_bus_driver, core); | 396 | return container_of(_drv, struct ps3_system_bus_driver, core); |
397 | } | 397 | } |
398 | static inline struct ps3_system_bus_device *ps3_dev_to_system_bus_dev( | 398 | static inline struct ps3_system_bus_device *ps3_dev_to_system_bus_dev( |
399 | struct device *_dev) | 399 | struct device *_dev) |
400 | { | 400 | { |
401 | return container_of(_dev, struct ps3_system_bus_device, core); | 401 | return container_of(_dev, struct ps3_system_bus_device, core); |
402 | } | 402 | } |
403 | static inline struct ps3_system_bus_driver * | 403 | static inline struct ps3_system_bus_driver * |
404 | ps3_system_bus_dev_to_system_bus_drv(struct ps3_system_bus_device *_dev) | 404 | ps3_system_bus_dev_to_system_bus_drv(struct ps3_system_bus_device *_dev) |
405 | { | 405 | { |
406 | BUG_ON(!_dev); | 406 | BUG_ON(!_dev); |
407 | BUG_ON(!_dev->core.driver); | 407 | BUG_ON(!_dev->core.driver); |
408 | return ps3_drv_to_system_bus_drv(_dev->core.driver); | 408 | return ps3_drv_to_system_bus_drv(_dev->core.driver); |
409 | } | 409 | } |
410 | 410 | ||
411 | /** | 411 | /** |
412 | * ps3_system_bus_set_drvdata - | 412 | * ps3_system_bus_set_drvdata - |
413 | * @dev: device structure | 413 | * @dev: device structure |
414 | * @data: Data to set | 414 | * @data: Data to set |
415 | */ | 415 | */ |
416 | 416 | ||
417 | static inline void ps3_system_bus_set_driver_data( | 417 | static inline void ps3_system_bus_set_driver_data( |
418 | struct ps3_system_bus_device *dev, void *data) | 418 | struct ps3_system_bus_device *dev, void *data) |
419 | { | 419 | { |
420 | dev->core.driver_data = data; | 420 | dev->core.driver_data = data; |
421 | } | 421 | } |
422 | static inline void *ps3_system_bus_get_driver_data( | 422 | static inline void *ps3_system_bus_get_driver_data( |
423 | struct ps3_system_bus_device *dev) | 423 | struct ps3_system_bus_device *dev) |
424 | { | 424 | { |
425 | return dev->core.driver_data; | 425 | return dev->core.driver_data; |
426 | } | 426 | } |
427 | 427 | ||
428 | /* These two need global scope for get_dma_ops(). */ | 428 | /* These two need global scope for get_dma_ops(). */ |
429 | 429 | ||
430 | extern struct bus_type ps3_system_bus_type; | 430 | extern struct bus_type ps3_system_bus_type; |
431 | 431 | ||
432 | /* system manager */ | 432 | /* system manager */ |
433 | 433 | ||
434 | struct ps3_sys_manager_ops { | 434 | struct ps3_sys_manager_ops { |
435 | struct ps3_system_bus_device *dev; | 435 | struct ps3_system_bus_device *dev; |
436 | void (*power_off)(struct ps3_system_bus_device *dev); | 436 | void (*power_off)(struct ps3_system_bus_device *dev); |
437 | void (*restart)(struct ps3_system_bus_device *dev); | 437 | void (*restart)(struct ps3_system_bus_device *dev); |
438 | }; | 438 | }; |
439 | 439 | ||
440 | void ps3_sys_manager_register_ops(const struct ps3_sys_manager_ops *ops); | 440 | void ps3_sys_manager_register_ops(const struct ps3_sys_manager_ops *ops); |
441 | void __noreturn ps3_sys_manager_power_off(void); | 441 | void __noreturn ps3_sys_manager_power_off(void); |
442 | void __noreturn ps3_sys_manager_restart(void); | 442 | void __noreturn ps3_sys_manager_restart(void); |
443 | void __noreturn ps3_sys_manager_halt(void); | 443 | void __noreturn ps3_sys_manager_halt(void); |
444 | int ps3_sys_manager_get_wol(void); | 444 | int ps3_sys_manager_get_wol(void); |
445 | void ps3_sys_manager_set_wol(int state); | 445 | void ps3_sys_manager_set_wol(int state); |
446 | 446 | ||
447 | struct ps3_prealloc { | 447 | struct ps3_prealloc { |
448 | const char *name; | 448 | const char *name; |
449 | void *address; | 449 | void *address; |
450 | unsigned long size; | 450 | unsigned long size; |
451 | unsigned long align; | 451 | unsigned long align; |
452 | }; | 452 | }; |
453 | 453 | ||
454 | extern struct ps3_prealloc ps3fb_videomemory; | 454 | extern struct ps3_prealloc ps3fb_videomemory; |
455 | extern struct ps3_prealloc ps3flash_bounce_buffer; | 455 | extern struct ps3_prealloc ps3flash_bounce_buffer; |
456 | 456 | ||
457 | /* logical performance monitor */ | 457 | /* logical performance monitor */ |
458 | 458 | ||
459 | /** | 459 | /** |
460 | * enum ps3_lpm_rights - Rigths granted by the system policy module. | 460 | * enum ps3_lpm_rights - Rigths granted by the system policy module. |
461 | * | 461 | * |
462 | * @PS3_LPM_RIGHTS_USE_LPM: The right to use the lpm. | 462 | * @PS3_LPM_RIGHTS_USE_LPM: The right to use the lpm. |
463 | * @PS3_LPM_RIGHTS_USE_TB: The right to use the internal trace buffer. | 463 | * @PS3_LPM_RIGHTS_USE_TB: The right to use the internal trace buffer. |
464 | */ | 464 | */ |
465 | 465 | ||
466 | enum ps3_lpm_rights { | 466 | enum ps3_lpm_rights { |
467 | PS3_LPM_RIGHTS_USE_LPM = 0x001, | 467 | PS3_LPM_RIGHTS_USE_LPM = 0x001, |
468 | PS3_LPM_RIGHTS_USE_TB = 0x100, | 468 | PS3_LPM_RIGHTS_USE_TB = 0x100, |
469 | }; | 469 | }; |
470 | 470 | ||
471 | /** | 471 | /** |
472 | * enum ps3_lpm_tb_type - Type of trace buffer lv1 should use. | 472 | * enum ps3_lpm_tb_type - Type of trace buffer lv1 should use. |
473 | * | 473 | * |
474 | * @PS3_LPM_TB_TYPE_NONE: Do not use a trace buffer. | 474 | * @PS3_LPM_TB_TYPE_NONE: Do not use a trace buffer. |
475 | * @PS3_LPM_RIGHTS_USE_TB: Use the lv1 internal trace buffer. Must have | 475 | * @PS3_LPM_RIGHTS_USE_TB: Use the lv1 internal trace buffer. Must have |
476 | * rights @PS3_LPM_RIGHTS_USE_TB. | 476 | * rights @PS3_LPM_RIGHTS_USE_TB. |
477 | */ | 477 | */ |
478 | 478 | ||
479 | enum ps3_lpm_tb_type { | 479 | enum ps3_lpm_tb_type { |
480 | PS3_LPM_TB_TYPE_NONE = 0, | 480 | PS3_LPM_TB_TYPE_NONE = 0, |
481 | PS3_LPM_TB_TYPE_INTERNAL = 1, | 481 | PS3_LPM_TB_TYPE_INTERNAL = 1, |
482 | }; | 482 | }; |
483 | 483 | ||
484 | int ps3_lpm_open(enum ps3_lpm_tb_type tb_type, void *tb_cache, | 484 | int ps3_lpm_open(enum ps3_lpm_tb_type tb_type, void *tb_cache, |
485 | u64 tb_cache_size); | 485 | u64 tb_cache_size); |
486 | int ps3_lpm_close(void); | 486 | int ps3_lpm_close(void); |
487 | int ps3_lpm_copy_tb(unsigned long offset, void *buf, unsigned long count, | 487 | int ps3_lpm_copy_tb(unsigned long offset, void *buf, unsigned long count, |
488 | unsigned long *bytes_copied); | 488 | unsigned long *bytes_copied); |
489 | int ps3_lpm_copy_tb_to_user(unsigned long offset, void __user *buf, | 489 | int ps3_lpm_copy_tb_to_user(unsigned long offset, void __user *buf, |
490 | unsigned long count, unsigned long *bytes_copied); | 490 | unsigned long count, unsigned long *bytes_copied); |
491 | void ps3_set_bookmark(u64 bookmark); | 491 | void ps3_set_bookmark(u64 bookmark); |
492 | void ps3_set_pm_bookmark(u64 tag, u64 incident, u64 th_id); | 492 | void ps3_set_pm_bookmark(u64 tag, u64 incident, u64 th_id); |
493 | int ps3_set_signal(u64 rtas_signal_group, u8 signal_bit, u16 sub_unit, | 493 | int ps3_set_signal(u64 rtas_signal_group, u8 signal_bit, u16 sub_unit, |
494 | u8 bus_word); | 494 | u8 bus_word); |
495 | 495 | ||
496 | u32 ps3_read_phys_ctr(u32 cpu, u32 phys_ctr); | 496 | u32 ps3_read_phys_ctr(u32 cpu, u32 phys_ctr); |
497 | void ps3_write_phys_ctr(u32 cpu, u32 phys_ctr, u32 val); | 497 | void ps3_write_phys_ctr(u32 cpu, u32 phys_ctr, u32 val); |
498 | u32 ps3_read_ctr(u32 cpu, u32 ctr); | 498 | u32 ps3_read_ctr(u32 cpu, u32 ctr); |
499 | void ps3_write_ctr(u32 cpu, u32 ctr, u32 val); | 499 | void ps3_write_ctr(u32 cpu, u32 ctr, u32 val); |
500 | 500 | ||
501 | u32 ps3_read_pm07_control(u32 cpu, u32 ctr); | 501 | u32 ps3_read_pm07_control(u32 cpu, u32 ctr); |
502 | void ps3_write_pm07_control(u32 cpu, u32 ctr, u32 val); | 502 | void ps3_write_pm07_control(u32 cpu, u32 ctr, u32 val); |
503 | u32 ps3_read_pm(u32 cpu, enum pm_reg_name reg); | 503 | u32 ps3_read_pm(u32 cpu, enum pm_reg_name reg); |
504 | void ps3_write_pm(u32 cpu, enum pm_reg_name reg, u32 val); | 504 | void ps3_write_pm(u32 cpu, enum pm_reg_name reg, u32 val); |
505 | 505 | ||
506 | u32 ps3_get_ctr_size(u32 cpu, u32 phys_ctr); | 506 | u32 ps3_get_ctr_size(u32 cpu, u32 phys_ctr); |
507 | void ps3_set_ctr_size(u32 cpu, u32 phys_ctr, u32 ctr_size); | 507 | void ps3_set_ctr_size(u32 cpu, u32 phys_ctr, u32 ctr_size); |
508 | 508 | ||
509 | void ps3_enable_pm(u32 cpu); | 509 | void ps3_enable_pm(u32 cpu); |
510 | void ps3_disable_pm(u32 cpu); | 510 | void ps3_disable_pm(u32 cpu); |
511 | void ps3_enable_pm_interrupts(u32 cpu, u32 thread, u32 mask); | 511 | void ps3_enable_pm_interrupts(u32 cpu, u32 thread, u32 mask); |
512 | void ps3_disable_pm_interrupts(u32 cpu); | 512 | void ps3_disable_pm_interrupts(u32 cpu); |
513 | 513 | ||
514 | u32 ps3_get_and_clear_pm_interrupts(u32 cpu); | 514 | u32 ps3_get_and_clear_pm_interrupts(u32 cpu); |
515 | void ps3_sync_irq(int node); | 515 | void ps3_sync_irq(int node); |
516 | u32 ps3_get_hw_thread_id(int cpu); | 516 | u32 ps3_get_hw_thread_id(int cpu); |
517 | u64 ps3_get_spe_id(void *arg); | 517 | u64 ps3_get_spe_id(void *arg); |
518 | 518 | ||
519 | /* mutex synchronizing GPU accesses and video mode changes */ | ||
520 | extern struct mutex ps3_gpu_mutex; | ||
521 | |||
519 | #endif | 522 | #endif |
520 | 523 |
arch/powerpc/include/asm/ps3av.h
1 | /* | 1 | /* |
2 | * PS3 AV backend support. | 2 | * PS3 AV backend support. |
3 | * | 3 | * |
4 | * Copyright (C) 2007 Sony Computer Entertainment Inc. | 4 | * Copyright (C) 2007 Sony Computer Entertainment Inc. |
5 | * Copyright 2007 Sony Corp. | 5 | * Copyright 2007 Sony Corp. |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License as published by | 8 | * it under the terms of the GNU General Public License as published by |
9 | * the Free Software Foundation; version 2 of the License. | 9 | * the Free Software Foundation; version 2 of the License. |
10 | * | 10 | * |
11 | * This program is distributed in the hope that it will be useful, | 11 | * This program is distributed in the hope that it will be useful, |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | * GNU General Public License for more details. | 14 | * GNU General Public License for more details. |
15 | * | 15 | * |
16 | * You should have received a copy of the GNU General Public License | 16 | * You should have received a copy of the GNU General Public License |
17 | * along with this program; if not, write to the Free Software | 17 | * along with this program; if not, write to the Free Software |
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
19 | */ | 19 | */ |
20 | 20 | ||
21 | #ifndef _ASM_POWERPC_PS3AV_H_ | 21 | #ifndef _ASM_POWERPC_PS3AV_H_ |
22 | #define _ASM_POWERPC_PS3AV_H_ | 22 | #define _ASM_POWERPC_PS3AV_H_ |
23 | 23 | ||
24 | /** command for ioctl() **/ | 24 | /** command for ioctl() **/ |
25 | #define PS3AV_VERSION 0x205 /* version of ps3av command */ | 25 | #define PS3AV_VERSION 0x205 /* version of ps3av command */ |
26 | 26 | ||
27 | #define PS3AV_CID_AV_INIT 0x00000001 | 27 | #define PS3AV_CID_AV_INIT 0x00000001 |
28 | #define PS3AV_CID_AV_FIN 0x00000002 | 28 | #define PS3AV_CID_AV_FIN 0x00000002 |
29 | #define PS3AV_CID_AV_GET_HW_CONF 0x00000003 | 29 | #define PS3AV_CID_AV_GET_HW_CONF 0x00000003 |
30 | #define PS3AV_CID_AV_GET_MONITOR_INFO 0x00000004 | 30 | #define PS3AV_CID_AV_GET_MONITOR_INFO 0x00000004 |
31 | #define PS3AV_CID_AV_ENABLE_EVENT 0x00000006 | 31 | #define PS3AV_CID_AV_ENABLE_EVENT 0x00000006 |
32 | #define PS3AV_CID_AV_DISABLE_EVENT 0x00000007 | 32 | #define PS3AV_CID_AV_DISABLE_EVENT 0x00000007 |
33 | #define PS3AV_CID_AV_TV_MUTE 0x0000000a | 33 | #define PS3AV_CID_AV_TV_MUTE 0x0000000a |
34 | 34 | ||
35 | #define PS3AV_CID_AV_VIDEO_CS 0x00010001 | 35 | #define PS3AV_CID_AV_VIDEO_CS 0x00010001 |
36 | #define PS3AV_CID_AV_VIDEO_MUTE 0x00010002 | 36 | #define PS3AV_CID_AV_VIDEO_MUTE 0x00010002 |
37 | #define PS3AV_CID_AV_VIDEO_DISABLE_SIG 0x00010003 | 37 | #define PS3AV_CID_AV_VIDEO_DISABLE_SIG 0x00010003 |
38 | #define PS3AV_CID_AV_AUDIO_PARAM 0x00020001 | 38 | #define PS3AV_CID_AV_AUDIO_PARAM 0x00020001 |
39 | #define PS3AV_CID_AV_AUDIO_MUTE 0x00020002 | 39 | #define PS3AV_CID_AV_AUDIO_MUTE 0x00020002 |
40 | #define PS3AV_CID_AV_HDMI_MODE 0x00040001 | 40 | #define PS3AV_CID_AV_HDMI_MODE 0x00040001 |
41 | 41 | ||
42 | #define PS3AV_CID_VIDEO_INIT 0x01000001 | 42 | #define PS3AV_CID_VIDEO_INIT 0x01000001 |
43 | #define PS3AV_CID_VIDEO_MODE 0x01000002 | 43 | #define PS3AV_CID_VIDEO_MODE 0x01000002 |
44 | #define PS3AV_CID_VIDEO_FORMAT 0x01000004 | 44 | #define PS3AV_CID_VIDEO_FORMAT 0x01000004 |
45 | #define PS3AV_CID_VIDEO_PITCH 0x01000005 | 45 | #define PS3AV_CID_VIDEO_PITCH 0x01000005 |
46 | 46 | ||
47 | #define PS3AV_CID_AUDIO_INIT 0x02000001 | 47 | #define PS3AV_CID_AUDIO_INIT 0x02000001 |
48 | #define PS3AV_CID_AUDIO_MODE 0x02000002 | 48 | #define PS3AV_CID_AUDIO_MODE 0x02000002 |
49 | #define PS3AV_CID_AUDIO_MUTE 0x02000003 | 49 | #define PS3AV_CID_AUDIO_MUTE 0x02000003 |
50 | #define PS3AV_CID_AUDIO_ACTIVE 0x02000004 | 50 | #define PS3AV_CID_AUDIO_ACTIVE 0x02000004 |
51 | #define PS3AV_CID_AUDIO_INACTIVE 0x02000005 | 51 | #define PS3AV_CID_AUDIO_INACTIVE 0x02000005 |
52 | #define PS3AV_CID_AUDIO_SPDIF_BIT 0x02000006 | 52 | #define PS3AV_CID_AUDIO_SPDIF_BIT 0x02000006 |
53 | #define PS3AV_CID_AUDIO_CTRL 0x02000007 | 53 | #define PS3AV_CID_AUDIO_CTRL 0x02000007 |
54 | 54 | ||
55 | #define PS3AV_CID_EVENT_UNPLUGGED 0x10000001 | 55 | #define PS3AV_CID_EVENT_UNPLUGGED 0x10000001 |
56 | #define PS3AV_CID_EVENT_PLUGGED 0x10000002 | 56 | #define PS3AV_CID_EVENT_PLUGGED 0x10000002 |
57 | #define PS3AV_CID_EVENT_HDCP_DONE 0x10000003 | 57 | #define PS3AV_CID_EVENT_HDCP_DONE 0x10000003 |
58 | #define PS3AV_CID_EVENT_HDCP_FAIL 0x10000004 | 58 | #define PS3AV_CID_EVENT_HDCP_FAIL 0x10000004 |
59 | #define PS3AV_CID_EVENT_HDCP_AUTH 0x10000005 | 59 | #define PS3AV_CID_EVENT_HDCP_AUTH 0x10000005 |
60 | #define PS3AV_CID_EVENT_HDCP_ERROR 0x10000006 | 60 | #define PS3AV_CID_EVENT_HDCP_ERROR 0x10000006 |
61 | 61 | ||
62 | #define PS3AV_CID_AVB_PARAM 0x04000001 | 62 | #define PS3AV_CID_AVB_PARAM 0x04000001 |
63 | 63 | ||
64 | /* max backend ports */ | 64 | /* max backend ports */ |
65 | #define PS3AV_HDMI_MAX 2 /* HDMI_0 HDMI_1 */ | 65 | #define PS3AV_HDMI_MAX 2 /* HDMI_0 HDMI_1 */ |
66 | #define PS3AV_AVMULTI_MAX 1 /* AVMULTI_0 */ | 66 | #define PS3AV_AVMULTI_MAX 1 /* AVMULTI_0 */ |
67 | #define PS3AV_AV_PORT_MAX (PS3AV_HDMI_MAX + PS3AV_AVMULTI_MAX) | 67 | #define PS3AV_AV_PORT_MAX (PS3AV_HDMI_MAX + PS3AV_AVMULTI_MAX) |
68 | #define PS3AV_OPT_PORT_MAX 1 /* SPDIF0 */ | 68 | #define PS3AV_OPT_PORT_MAX 1 /* SPDIF0 */ |
69 | #define PS3AV_HEAD_MAX 2 /* HEAD_A HEAD_B */ | 69 | #define PS3AV_HEAD_MAX 2 /* HEAD_A HEAD_B */ |
70 | 70 | ||
71 | /* num of pkt for PS3AV_CID_AVB_PARAM */ | 71 | /* num of pkt for PS3AV_CID_AVB_PARAM */ |
72 | #define PS3AV_AVB_NUM_VIDEO PS3AV_HEAD_MAX | 72 | #define PS3AV_AVB_NUM_VIDEO PS3AV_HEAD_MAX |
73 | #define PS3AV_AVB_NUM_AUDIO 0 /* not supported */ | 73 | #define PS3AV_AVB_NUM_AUDIO 0 /* not supported */ |
74 | #define PS3AV_AVB_NUM_AV_VIDEO PS3AV_AV_PORT_MAX | 74 | #define PS3AV_AVB_NUM_AV_VIDEO PS3AV_AV_PORT_MAX |
75 | #define PS3AV_AVB_NUM_AV_AUDIO PS3AV_HDMI_MAX | 75 | #define PS3AV_AVB_NUM_AV_AUDIO PS3AV_HDMI_MAX |
76 | 76 | ||
77 | #define PS3AV_MUTE_PORT_MAX 1 /* num of ports in mute pkt */ | 77 | #define PS3AV_MUTE_PORT_MAX 1 /* num of ports in mute pkt */ |
78 | 78 | ||
79 | /* event_bit */ | 79 | /* event_bit */ |
80 | #define PS3AV_CMD_EVENT_BIT_UNPLUGGED (1 << 0) | 80 | #define PS3AV_CMD_EVENT_BIT_UNPLUGGED (1 << 0) |
81 | #define PS3AV_CMD_EVENT_BIT_PLUGGED (1 << 1) | 81 | #define PS3AV_CMD_EVENT_BIT_PLUGGED (1 << 1) |
82 | #define PS3AV_CMD_EVENT_BIT_HDCP_DONE (1 << 2) | 82 | #define PS3AV_CMD_EVENT_BIT_HDCP_DONE (1 << 2) |
83 | #define PS3AV_CMD_EVENT_BIT_HDCP_FAIL (1 << 3) | 83 | #define PS3AV_CMD_EVENT_BIT_HDCP_FAIL (1 << 3) |
84 | #define PS3AV_CMD_EVENT_BIT_HDCP_REAUTH (1 << 4) | 84 | #define PS3AV_CMD_EVENT_BIT_HDCP_REAUTH (1 << 4) |
85 | #define PS3AV_CMD_EVENT_BIT_HDCP_TOPOLOGY (1 << 5) | 85 | #define PS3AV_CMD_EVENT_BIT_HDCP_TOPOLOGY (1 << 5) |
86 | 86 | ||
87 | /* common params */ | 87 | /* common params */ |
88 | /* mute */ | 88 | /* mute */ |
89 | #define PS3AV_CMD_MUTE_OFF 0x0000 | 89 | #define PS3AV_CMD_MUTE_OFF 0x0000 |
90 | #define PS3AV_CMD_MUTE_ON 0x0001 | 90 | #define PS3AV_CMD_MUTE_ON 0x0001 |
91 | /* avport */ | 91 | /* avport */ |
92 | #define PS3AV_CMD_AVPORT_HDMI_0 0x0000 | 92 | #define PS3AV_CMD_AVPORT_HDMI_0 0x0000 |
93 | #define PS3AV_CMD_AVPORT_HDMI_1 0x0001 | 93 | #define PS3AV_CMD_AVPORT_HDMI_1 0x0001 |
94 | #define PS3AV_CMD_AVPORT_AVMULTI_0 0x0010 | 94 | #define PS3AV_CMD_AVPORT_AVMULTI_0 0x0010 |
95 | #define PS3AV_CMD_AVPORT_SPDIF_0 0x0020 | 95 | #define PS3AV_CMD_AVPORT_SPDIF_0 0x0020 |
96 | #define PS3AV_CMD_AVPORT_SPDIF_1 0x0021 | 96 | #define PS3AV_CMD_AVPORT_SPDIF_1 0x0021 |
97 | 97 | ||
98 | /* for av backend */ | 98 | /* for av backend */ |
99 | /* av_mclk */ | 99 | /* av_mclk */ |
100 | #define PS3AV_CMD_AV_MCLK_128 0x0000 | 100 | #define PS3AV_CMD_AV_MCLK_128 0x0000 |
101 | #define PS3AV_CMD_AV_MCLK_256 0x0001 | 101 | #define PS3AV_CMD_AV_MCLK_256 0x0001 |
102 | #define PS3AV_CMD_AV_MCLK_512 0x0003 | 102 | #define PS3AV_CMD_AV_MCLK_512 0x0003 |
103 | /* av_inputlen */ | 103 | /* av_inputlen */ |
104 | #define PS3AV_CMD_AV_INPUTLEN_16 0x02 | 104 | #define PS3AV_CMD_AV_INPUTLEN_16 0x02 |
105 | #define PS3AV_CMD_AV_INPUTLEN_20 0x0a | 105 | #define PS3AV_CMD_AV_INPUTLEN_20 0x0a |
106 | #define PS3AV_CMD_AV_INPUTLEN_24 0x0b | 106 | #define PS3AV_CMD_AV_INPUTLEN_24 0x0b |
107 | /* alayout */ | 107 | /* alayout */ |
108 | #define PS3AV_CMD_AV_LAYOUT_32 (1 << 0) | 108 | #define PS3AV_CMD_AV_LAYOUT_32 (1 << 0) |
109 | #define PS3AV_CMD_AV_LAYOUT_44 (1 << 1) | 109 | #define PS3AV_CMD_AV_LAYOUT_44 (1 << 1) |
110 | #define PS3AV_CMD_AV_LAYOUT_48 (1 << 2) | 110 | #define PS3AV_CMD_AV_LAYOUT_48 (1 << 2) |
111 | #define PS3AV_CMD_AV_LAYOUT_88 (1 << 3) | 111 | #define PS3AV_CMD_AV_LAYOUT_88 (1 << 3) |
112 | #define PS3AV_CMD_AV_LAYOUT_96 (1 << 4) | 112 | #define PS3AV_CMD_AV_LAYOUT_96 (1 << 4) |
113 | #define PS3AV_CMD_AV_LAYOUT_176 (1 << 5) | 113 | #define PS3AV_CMD_AV_LAYOUT_176 (1 << 5) |
114 | #define PS3AV_CMD_AV_LAYOUT_192 (1 << 6) | 114 | #define PS3AV_CMD_AV_LAYOUT_192 (1 << 6) |
115 | /* hdmi_mode */ | 115 | /* hdmi_mode */ |
116 | #define PS3AV_CMD_AV_HDMI_MODE_NORMAL 0xff | 116 | #define PS3AV_CMD_AV_HDMI_MODE_NORMAL 0xff |
117 | #define PS3AV_CMD_AV_HDMI_HDCP_OFF 0x01 | 117 | #define PS3AV_CMD_AV_HDMI_HDCP_OFF 0x01 |
118 | #define PS3AV_CMD_AV_HDMI_EDID_PASS 0x80 | 118 | #define PS3AV_CMD_AV_HDMI_EDID_PASS 0x80 |
119 | #define PS3AV_CMD_AV_HDMI_DVI 0x40 | 119 | #define PS3AV_CMD_AV_HDMI_DVI 0x40 |
120 | 120 | ||
121 | /* for video module */ | 121 | /* for video module */ |
122 | /* video_head */ | 122 | /* video_head */ |
123 | #define PS3AV_CMD_VIDEO_HEAD_A 0x0000 | 123 | #define PS3AV_CMD_VIDEO_HEAD_A 0x0000 |
124 | #define PS3AV_CMD_VIDEO_HEAD_B 0x0001 | 124 | #define PS3AV_CMD_VIDEO_HEAD_B 0x0001 |
125 | /* video_cs_out video_cs_in */ | 125 | /* video_cs_out video_cs_in */ |
126 | #define PS3AV_CMD_VIDEO_CS_NONE 0x0000 | 126 | #define PS3AV_CMD_VIDEO_CS_NONE 0x0000 |
127 | #define PS3AV_CMD_VIDEO_CS_RGB_8 0x0001 | 127 | #define PS3AV_CMD_VIDEO_CS_RGB_8 0x0001 |
128 | #define PS3AV_CMD_VIDEO_CS_YUV444_8 0x0002 | 128 | #define PS3AV_CMD_VIDEO_CS_YUV444_8 0x0002 |
129 | #define PS3AV_CMD_VIDEO_CS_YUV422_8 0x0003 | 129 | #define PS3AV_CMD_VIDEO_CS_YUV422_8 0x0003 |
130 | #define PS3AV_CMD_VIDEO_CS_XVYCC_8 0x0004 | 130 | #define PS3AV_CMD_VIDEO_CS_XVYCC_8 0x0004 |
131 | #define PS3AV_CMD_VIDEO_CS_RGB_10 0x0005 | 131 | #define PS3AV_CMD_VIDEO_CS_RGB_10 0x0005 |
132 | #define PS3AV_CMD_VIDEO_CS_YUV444_10 0x0006 | 132 | #define PS3AV_CMD_VIDEO_CS_YUV444_10 0x0006 |
133 | #define PS3AV_CMD_VIDEO_CS_YUV422_10 0x0007 | 133 | #define PS3AV_CMD_VIDEO_CS_YUV422_10 0x0007 |
134 | #define PS3AV_CMD_VIDEO_CS_XVYCC_10 0x0008 | 134 | #define PS3AV_CMD_VIDEO_CS_XVYCC_10 0x0008 |
135 | #define PS3AV_CMD_VIDEO_CS_RGB_12 0x0009 | 135 | #define PS3AV_CMD_VIDEO_CS_RGB_12 0x0009 |
136 | #define PS3AV_CMD_VIDEO_CS_YUV444_12 0x000a | 136 | #define PS3AV_CMD_VIDEO_CS_YUV444_12 0x000a |
137 | #define PS3AV_CMD_VIDEO_CS_YUV422_12 0x000b | 137 | #define PS3AV_CMD_VIDEO_CS_YUV422_12 0x000b |
138 | #define PS3AV_CMD_VIDEO_CS_XVYCC_12 0x000c | 138 | #define PS3AV_CMD_VIDEO_CS_XVYCC_12 0x000c |
139 | /* video_vid */ | 139 | /* video_vid */ |
140 | #define PS3AV_CMD_VIDEO_VID_NONE 0x0000 | 140 | #define PS3AV_CMD_VIDEO_VID_NONE 0x0000 |
141 | #define PS3AV_CMD_VIDEO_VID_480I 0x0001 | 141 | #define PS3AV_CMD_VIDEO_VID_480I 0x0001 |
142 | #define PS3AV_CMD_VIDEO_VID_576I 0x0003 | 142 | #define PS3AV_CMD_VIDEO_VID_576I 0x0003 |
143 | #define PS3AV_CMD_VIDEO_VID_480P 0x0005 | 143 | #define PS3AV_CMD_VIDEO_VID_480P 0x0005 |
144 | #define PS3AV_CMD_VIDEO_VID_576P 0x0006 | 144 | #define PS3AV_CMD_VIDEO_VID_576P 0x0006 |
145 | #define PS3AV_CMD_VIDEO_VID_1080I_60HZ 0x0007 | 145 | #define PS3AV_CMD_VIDEO_VID_1080I_60HZ 0x0007 |
146 | #define PS3AV_CMD_VIDEO_VID_1080I_50HZ 0x0008 | 146 | #define PS3AV_CMD_VIDEO_VID_1080I_50HZ 0x0008 |
147 | #define PS3AV_CMD_VIDEO_VID_720P_60HZ 0x0009 | 147 | #define PS3AV_CMD_VIDEO_VID_720P_60HZ 0x0009 |
148 | #define PS3AV_CMD_VIDEO_VID_720P_50HZ 0x000a | 148 | #define PS3AV_CMD_VIDEO_VID_720P_50HZ 0x000a |
149 | #define PS3AV_CMD_VIDEO_VID_1080P_60HZ 0x000b | 149 | #define PS3AV_CMD_VIDEO_VID_1080P_60HZ 0x000b |
150 | #define PS3AV_CMD_VIDEO_VID_1080P_50HZ 0x000c | 150 | #define PS3AV_CMD_VIDEO_VID_1080P_50HZ 0x000c |
151 | #define PS3AV_CMD_VIDEO_VID_WXGA 0x000d | 151 | #define PS3AV_CMD_VIDEO_VID_WXGA 0x000d |
152 | #define PS3AV_CMD_VIDEO_VID_SXGA 0x000e | 152 | #define PS3AV_CMD_VIDEO_VID_SXGA 0x000e |
153 | #define PS3AV_CMD_VIDEO_VID_WUXGA 0x000f | 153 | #define PS3AV_CMD_VIDEO_VID_WUXGA 0x000f |
154 | #define PS3AV_CMD_VIDEO_VID_480I_A 0x0010 | 154 | #define PS3AV_CMD_VIDEO_VID_480I_A 0x0010 |
155 | /* video_format */ | 155 | /* video_format */ |
156 | #define PS3AV_CMD_VIDEO_FORMAT_BLACK 0x0000 | 156 | #define PS3AV_CMD_VIDEO_FORMAT_BLACK 0x0000 |
157 | #define PS3AV_CMD_VIDEO_FORMAT_ARGB_8BIT 0x0007 | 157 | #define PS3AV_CMD_VIDEO_FORMAT_ARGB_8BIT 0x0007 |
158 | /* video_order */ | 158 | /* video_order */ |
159 | #define PS3AV_CMD_VIDEO_ORDER_RGB 0x0000 | 159 | #define PS3AV_CMD_VIDEO_ORDER_RGB 0x0000 |
160 | #define PS3AV_CMD_VIDEO_ORDER_BGR 0x0001 | 160 | #define PS3AV_CMD_VIDEO_ORDER_BGR 0x0001 |
161 | /* video_fmt */ | 161 | /* video_fmt */ |
162 | #define PS3AV_CMD_VIDEO_FMT_X8R8G8B8 0x0000 | 162 | #define PS3AV_CMD_VIDEO_FMT_X8R8G8B8 0x0000 |
163 | /* video_out_format */ | 163 | /* video_out_format */ |
164 | #define PS3AV_CMD_VIDEO_OUT_FORMAT_RGB_12BIT 0x0000 | 164 | #define PS3AV_CMD_VIDEO_OUT_FORMAT_RGB_12BIT 0x0000 |
165 | /* video_cl_cnv */ | 165 | /* video_cl_cnv */ |
166 | #define PS3AV_CMD_VIDEO_CL_CNV_ENABLE_LUT 0x0000 | 166 | #define PS3AV_CMD_VIDEO_CL_CNV_ENABLE_LUT 0x0000 |
167 | #define PS3AV_CMD_VIDEO_CL_CNV_DISABLE_LUT 0x0010 | 167 | #define PS3AV_CMD_VIDEO_CL_CNV_DISABLE_LUT 0x0010 |
168 | /* video_sync */ | 168 | /* video_sync */ |
169 | #define PS3AV_CMD_VIDEO_SYNC_VSYNC 0x0001 | 169 | #define PS3AV_CMD_VIDEO_SYNC_VSYNC 0x0001 |
170 | #define PS3AV_CMD_VIDEO_SYNC_CSYNC 0x0004 | 170 | #define PS3AV_CMD_VIDEO_SYNC_CSYNC 0x0004 |
171 | #define PS3AV_CMD_VIDEO_SYNC_HSYNC 0x0010 | 171 | #define PS3AV_CMD_VIDEO_SYNC_HSYNC 0x0010 |
172 | 172 | ||
173 | /* for audio module */ | 173 | /* for audio module */ |
174 | /* num_of_ch */ | 174 | /* num_of_ch */ |
175 | #define PS3AV_CMD_AUDIO_NUM_OF_CH_2 0x0000 | 175 | #define PS3AV_CMD_AUDIO_NUM_OF_CH_2 0x0000 |
176 | #define PS3AV_CMD_AUDIO_NUM_OF_CH_3 0x0001 | 176 | #define PS3AV_CMD_AUDIO_NUM_OF_CH_3 0x0001 |
177 | #define PS3AV_CMD_AUDIO_NUM_OF_CH_4 0x0002 | 177 | #define PS3AV_CMD_AUDIO_NUM_OF_CH_4 0x0002 |
178 | #define PS3AV_CMD_AUDIO_NUM_OF_CH_5 0x0003 | 178 | #define PS3AV_CMD_AUDIO_NUM_OF_CH_5 0x0003 |
179 | #define PS3AV_CMD_AUDIO_NUM_OF_CH_6 0x0004 | 179 | #define PS3AV_CMD_AUDIO_NUM_OF_CH_6 0x0004 |
180 | #define PS3AV_CMD_AUDIO_NUM_OF_CH_7 0x0005 | 180 | #define PS3AV_CMD_AUDIO_NUM_OF_CH_7 0x0005 |
181 | #define PS3AV_CMD_AUDIO_NUM_OF_CH_8 0x0006 | 181 | #define PS3AV_CMD_AUDIO_NUM_OF_CH_8 0x0006 |
182 | /* audio_fs */ | 182 | /* audio_fs */ |
183 | #define PS3AV_CMD_AUDIO_FS_32K 0x0001 | 183 | #define PS3AV_CMD_AUDIO_FS_32K 0x0001 |
184 | #define PS3AV_CMD_AUDIO_FS_44K 0x0002 | 184 | #define PS3AV_CMD_AUDIO_FS_44K 0x0002 |
185 | #define PS3AV_CMD_AUDIO_FS_48K 0x0003 | 185 | #define PS3AV_CMD_AUDIO_FS_48K 0x0003 |
186 | #define PS3AV_CMD_AUDIO_FS_88K 0x0004 | 186 | #define PS3AV_CMD_AUDIO_FS_88K 0x0004 |
187 | #define PS3AV_CMD_AUDIO_FS_96K 0x0005 | 187 | #define PS3AV_CMD_AUDIO_FS_96K 0x0005 |
188 | #define PS3AV_CMD_AUDIO_FS_176K 0x0006 | 188 | #define PS3AV_CMD_AUDIO_FS_176K 0x0006 |
189 | #define PS3AV_CMD_AUDIO_FS_192K 0x0007 | 189 | #define PS3AV_CMD_AUDIO_FS_192K 0x0007 |
190 | /* audio_word_bits */ | 190 | /* audio_word_bits */ |
191 | #define PS3AV_CMD_AUDIO_WORD_BITS_16 0x0001 | 191 | #define PS3AV_CMD_AUDIO_WORD_BITS_16 0x0001 |
192 | #define PS3AV_CMD_AUDIO_WORD_BITS_20 0x0002 | 192 | #define PS3AV_CMD_AUDIO_WORD_BITS_20 0x0002 |
193 | #define PS3AV_CMD_AUDIO_WORD_BITS_24 0x0003 | 193 | #define PS3AV_CMD_AUDIO_WORD_BITS_24 0x0003 |
194 | /* audio_format */ | 194 | /* audio_format */ |
195 | #define PS3AV_CMD_AUDIO_FORMAT_PCM 0x0001 | 195 | #define PS3AV_CMD_AUDIO_FORMAT_PCM 0x0001 |
196 | #define PS3AV_CMD_AUDIO_FORMAT_BITSTREAM 0x00ff | 196 | #define PS3AV_CMD_AUDIO_FORMAT_BITSTREAM 0x00ff |
197 | /* audio_source */ | 197 | /* audio_source */ |
198 | #define PS3AV_CMD_AUDIO_SOURCE_SERIAL 0x0000 | 198 | #define PS3AV_CMD_AUDIO_SOURCE_SERIAL 0x0000 |
199 | #define PS3AV_CMD_AUDIO_SOURCE_SPDIF 0x0001 | 199 | #define PS3AV_CMD_AUDIO_SOURCE_SPDIF 0x0001 |
200 | /* audio_swap */ | 200 | /* audio_swap */ |
201 | #define PS3AV_CMD_AUDIO_SWAP_0 0x0000 | 201 | #define PS3AV_CMD_AUDIO_SWAP_0 0x0000 |
202 | #define PS3AV_CMD_AUDIO_SWAP_1 0x0000 | 202 | #define PS3AV_CMD_AUDIO_SWAP_1 0x0000 |
203 | /* audio_map */ | 203 | /* audio_map */ |
204 | #define PS3AV_CMD_AUDIO_MAP_OUTPUT_0 0x0000 | 204 | #define PS3AV_CMD_AUDIO_MAP_OUTPUT_0 0x0000 |
205 | #define PS3AV_CMD_AUDIO_MAP_OUTPUT_1 0x0001 | 205 | #define PS3AV_CMD_AUDIO_MAP_OUTPUT_1 0x0001 |
206 | #define PS3AV_CMD_AUDIO_MAP_OUTPUT_2 0x0002 | 206 | #define PS3AV_CMD_AUDIO_MAP_OUTPUT_2 0x0002 |
207 | #define PS3AV_CMD_AUDIO_MAP_OUTPUT_3 0x0003 | 207 | #define PS3AV_CMD_AUDIO_MAP_OUTPUT_3 0x0003 |
208 | /* audio_layout */ | 208 | /* audio_layout */ |
209 | #define PS3AV_CMD_AUDIO_LAYOUT_2CH 0x0000 | 209 | #define PS3AV_CMD_AUDIO_LAYOUT_2CH 0x0000 |
210 | #define PS3AV_CMD_AUDIO_LAYOUT_6CH 0x000b /* LREClr */ | 210 | #define PS3AV_CMD_AUDIO_LAYOUT_6CH 0x000b /* LREClr */ |
211 | #define PS3AV_CMD_AUDIO_LAYOUT_8CH 0x001f /* LREClrXY */ | 211 | #define PS3AV_CMD_AUDIO_LAYOUT_8CH 0x001f /* LREClrXY */ |
212 | /* audio_downmix */ | 212 | /* audio_downmix */ |
213 | #define PS3AV_CMD_AUDIO_DOWNMIX_PERMITTED 0x0000 | 213 | #define PS3AV_CMD_AUDIO_DOWNMIX_PERMITTED 0x0000 |
214 | #define PS3AV_CMD_AUDIO_DOWNMIX_PROHIBITED 0x0001 | 214 | #define PS3AV_CMD_AUDIO_DOWNMIX_PROHIBITED 0x0001 |
215 | 215 | ||
216 | /* audio_port */ | 216 | /* audio_port */ |
217 | #define PS3AV_CMD_AUDIO_PORT_HDMI_0 ( 1 << 0 ) | 217 | #define PS3AV_CMD_AUDIO_PORT_HDMI_0 ( 1 << 0 ) |
218 | #define PS3AV_CMD_AUDIO_PORT_HDMI_1 ( 1 << 1 ) | 218 | #define PS3AV_CMD_AUDIO_PORT_HDMI_1 ( 1 << 1 ) |
219 | #define PS3AV_CMD_AUDIO_PORT_AVMULTI_0 ( 1 << 10 ) | 219 | #define PS3AV_CMD_AUDIO_PORT_AVMULTI_0 ( 1 << 10 ) |
220 | #define PS3AV_CMD_AUDIO_PORT_SPDIF_0 ( 1 << 20 ) | 220 | #define PS3AV_CMD_AUDIO_PORT_SPDIF_0 ( 1 << 20 ) |
221 | #define PS3AV_CMD_AUDIO_PORT_SPDIF_1 ( 1 << 21 ) | 221 | #define PS3AV_CMD_AUDIO_PORT_SPDIF_1 ( 1 << 21 ) |
222 | 222 | ||
223 | /* audio_ctrl_id */ | 223 | /* audio_ctrl_id */ |
224 | #define PS3AV_CMD_AUDIO_CTRL_ID_DAC_RESET 0x0000 | 224 | #define PS3AV_CMD_AUDIO_CTRL_ID_DAC_RESET 0x0000 |
225 | #define PS3AV_CMD_AUDIO_CTRL_ID_DAC_DE_EMPHASIS 0x0001 | 225 | #define PS3AV_CMD_AUDIO_CTRL_ID_DAC_DE_EMPHASIS 0x0001 |
226 | #define PS3AV_CMD_AUDIO_CTRL_ID_AVCLK 0x0002 | 226 | #define PS3AV_CMD_AUDIO_CTRL_ID_AVCLK 0x0002 |
227 | /* audio_ctrl_data[0] reset */ | 227 | /* audio_ctrl_data[0] reset */ |
228 | #define PS3AV_CMD_AUDIO_CTRL_RESET_NEGATE 0x0000 | 228 | #define PS3AV_CMD_AUDIO_CTRL_RESET_NEGATE 0x0000 |
229 | #define PS3AV_CMD_AUDIO_CTRL_RESET_ASSERT 0x0001 | 229 | #define PS3AV_CMD_AUDIO_CTRL_RESET_ASSERT 0x0001 |
230 | /* audio_ctrl_data[0] de-emphasis */ | 230 | /* audio_ctrl_data[0] de-emphasis */ |
231 | #define PS3AV_CMD_AUDIO_CTRL_DE_EMPHASIS_OFF 0x0000 | 231 | #define PS3AV_CMD_AUDIO_CTRL_DE_EMPHASIS_OFF 0x0000 |
232 | #define PS3AV_CMD_AUDIO_CTRL_DE_EMPHASIS_ON 0x0001 | 232 | #define PS3AV_CMD_AUDIO_CTRL_DE_EMPHASIS_ON 0x0001 |
233 | /* audio_ctrl_data[0] avclk */ | 233 | /* audio_ctrl_data[0] avclk */ |
234 | #define PS3AV_CMD_AUDIO_CTRL_AVCLK_22 0x0000 | 234 | #define PS3AV_CMD_AUDIO_CTRL_AVCLK_22 0x0000 |
235 | #define PS3AV_CMD_AUDIO_CTRL_AVCLK_18 0x0001 | 235 | #define PS3AV_CMD_AUDIO_CTRL_AVCLK_18 0x0001 |
236 | 236 | ||
237 | /* av_vid */ | 237 | /* av_vid */ |
238 | /* do not use these params directly, use vid_video2av */ | 238 | /* do not use these params directly, use vid_video2av */ |
239 | #define PS3AV_CMD_AV_VID_480I 0x0000 | 239 | #define PS3AV_CMD_AV_VID_480I 0x0000 |
240 | #define PS3AV_CMD_AV_VID_480P 0x0001 | 240 | #define PS3AV_CMD_AV_VID_480P 0x0001 |
241 | #define PS3AV_CMD_AV_VID_720P_60HZ 0x0002 | 241 | #define PS3AV_CMD_AV_VID_720P_60HZ 0x0002 |
242 | #define PS3AV_CMD_AV_VID_1080I_60HZ 0x0003 | 242 | #define PS3AV_CMD_AV_VID_1080I_60HZ 0x0003 |
243 | #define PS3AV_CMD_AV_VID_1080P_60HZ 0x0004 | 243 | #define PS3AV_CMD_AV_VID_1080P_60HZ 0x0004 |
244 | #define PS3AV_CMD_AV_VID_576I 0x0005 | 244 | #define PS3AV_CMD_AV_VID_576I 0x0005 |
245 | #define PS3AV_CMD_AV_VID_576P 0x0006 | 245 | #define PS3AV_CMD_AV_VID_576P 0x0006 |
246 | #define PS3AV_CMD_AV_VID_720P_50HZ 0x0007 | 246 | #define PS3AV_CMD_AV_VID_720P_50HZ 0x0007 |
247 | #define PS3AV_CMD_AV_VID_1080I_50HZ 0x0008 | 247 | #define PS3AV_CMD_AV_VID_1080I_50HZ 0x0008 |
248 | #define PS3AV_CMD_AV_VID_1080P_50HZ 0x0009 | 248 | #define PS3AV_CMD_AV_VID_1080P_50HZ 0x0009 |
249 | #define PS3AV_CMD_AV_VID_WXGA 0x000a | 249 | #define PS3AV_CMD_AV_VID_WXGA 0x000a |
250 | #define PS3AV_CMD_AV_VID_SXGA 0x000b | 250 | #define PS3AV_CMD_AV_VID_SXGA 0x000b |
251 | #define PS3AV_CMD_AV_VID_WUXGA 0x000c | 251 | #define PS3AV_CMD_AV_VID_WUXGA 0x000c |
252 | /* av_cs_out av_cs_in */ | 252 | /* av_cs_out av_cs_in */ |
253 | /* use cs_video2av() */ | 253 | /* use cs_video2av() */ |
254 | #define PS3AV_CMD_AV_CS_RGB_8 0x0000 | 254 | #define PS3AV_CMD_AV_CS_RGB_8 0x0000 |
255 | #define PS3AV_CMD_AV_CS_YUV444_8 0x0001 | 255 | #define PS3AV_CMD_AV_CS_YUV444_8 0x0001 |
256 | #define PS3AV_CMD_AV_CS_YUV422_8 0x0002 | 256 | #define PS3AV_CMD_AV_CS_YUV422_8 0x0002 |
257 | #define PS3AV_CMD_AV_CS_XVYCC_8 0x0003 | 257 | #define PS3AV_CMD_AV_CS_XVYCC_8 0x0003 |
258 | #define PS3AV_CMD_AV_CS_RGB_10 0x0004 | 258 | #define PS3AV_CMD_AV_CS_RGB_10 0x0004 |
259 | #define PS3AV_CMD_AV_CS_YUV444_10 0x0005 | 259 | #define PS3AV_CMD_AV_CS_YUV444_10 0x0005 |
260 | #define PS3AV_CMD_AV_CS_YUV422_10 0x0006 | 260 | #define PS3AV_CMD_AV_CS_YUV422_10 0x0006 |
261 | #define PS3AV_CMD_AV_CS_XVYCC_10 0x0007 | 261 | #define PS3AV_CMD_AV_CS_XVYCC_10 0x0007 |
262 | #define PS3AV_CMD_AV_CS_RGB_12 0x0008 | 262 | #define PS3AV_CMD_AV_CS_RGB_12 0x0008 |
263 | #define PS3AV_CMD_AV_CS_YUV444_12 0x0009 | 263 | #define PS3AV_CMD_AV_CS_YUV444_12 0x0009 |
264 | #define PS3AV_CMD_AV_CS_YUV422_12 0x000a | 264 | #define PS3AV_CMD_AV_CS_YUV422_12 0x000a |
265 | #define PS3AV_CMD_AV_CS_XVYCC_12 0x000b | 265 | #define PS3AV_CMD_AV_CS_XVYCC_12 0x000b |
266 | #define PS3AV_CMD_AV_CS_8 0x0000 | 266 | #define PS3AV_CMD_AV_CS_8 0x0000 |
267 | #define PS3AV_CMD_AV_CS_10 0x0001 | 267 | #define PS3AV_CMD_AV_CS_10 0x0001 |
268 | #define PS3AV_CMD_AV_CS_12 0x0002 | 268 | #define PS3AV_CMD_AV_CS_12 0x0002 |
269 | /* dither */ | 269 | /* dither */ |
270 | #define PS3AV_CMD_AV_DITHER_OFF 0x0000 | 270 | #define PS3AV_CMD_AV_DITHER_OFF 0x0000 |
271 | #define PS3AV_CMD_AV_DITHER_ON 0x0001 | 271 | #define PS3AV_CMD_AV_DITHER_ON 0x0001 |
272 | #define PS3AV_CMD_AV_DITHER_8BIT 0x0000 | 272 | #define PS3AV_CMD_AV_DITHER_8BIT 0x0000 |
273 | #define PS3AV_CMD_AV_DITHER_10BIT 0x0002 | 273 | #define PS3AV_CMD_AV_DITHER_10BIT 0x0002 |
274 | #define PS3AV_CMD_AV_DITHER_12BIT 0x0004 | 274 | #define PS3AV_CMD_AV_DITHER_12BIT 0x0004 |
275 | /* super_white */ | 275 | /* super_white */ |
276 | #define PS3AV_CMD_AV_SUPER_WHITE_OFF 0x0000 | 276 | #define PS3AV_CMD_AV_SUPER_WHITE_OFF 0x0000 |
277 | #define PS3AV_CMD_AV_SUPER_WHITE_ON 0x0001 | 277 | #define PS3AV_CMD_AV_SUPER_WHITE_ON 0x0001 |
278 | /* aspect */ | 278 | /* aspect */ |
279 | #define PS3AV_CMD_AV_ASPECT_16_9 0x0000 | 279 | #define PS3AV_CMD_AV_ASPECT_16_9 0x0000 |
280 | #define PS3AV_CMD_AV_ASPECT_4_3 0x0001 | 280 | #define PS3AV_CMD_AV_ASPECT_4_3 0x0001 |
281 | /* video_cs_cnv() */ | 281 | /* video_cs_cnv() */ |
282 | #define PS3AV_CMD_VIDEO_CS_RGB 0x0001 | 282 | #define PS3AV_CMD_VIDEO_CS_RGB 0x0001 |
283 | #define PS3AV_CMD_VIDEO_CS_YUV422 0x0002 | 283 | #define PS3AV_CMD_VIDEO_CS_YUV422 0x0002 |
284 | #define PS3AV_CMD_VIDEO_CS_YUV444 0x0003 | 284 | #define PS3AV_CMD_VIDEO_CS_YUV444 0x0003 |
285 | 285 | ||
286 | /* for broadcast automode */ | 286 | /* for broadcast automode */ |
287 | #define PS3AV_RESBIT_720x480P 0x0003 /* 0x0001 | 0x0002 */ | 287 | #define PS3AV_RESBIT_720x480P 0x0003 /* 0x0001 | 0x0002 */ |
288 | #define PS3AV_RESBIT_720x576P 0x0003 /* 0x0001 | 0x0002 */ | 288 | #define PS3AV_RESBIT_720x576P 0x0003 /* 0x0001 | 0x0002 */ |
289 | #define PS3AV_RESBIT_1280x720P 0x0004 | 289 | #define PS3AV_RESBIT_1280x720P 0x0004 |
290 | #define PS3AV_RESBIT_1920x1080I 0x0008 | 290 | #define PS3AV_RESBIT_1920x1080I 0x0008 |
291 | #define PS3AV_RESBIT_1920x1080P 0x4000 | 291 | #define PS3AV_RESBIT_1920x1080P 0x4000 |
292 | #define PS3AV_RES_MASK_60 (PS3AV_RESBIT_720x480P \ | 292 | #define PS3AV_RES_MASK_60 (PS3AV_RESBIT_720x480P \ |
293 | | PS3AV_RESBIT_1280x720P \ | 293 | | PS3AV_RESBIT_1280x720P \ |
294 | | PS3AV_RESBIT_1920x1080I \ | 294 | | PS3AV_RESBIT_1920x1080I \ |
295 | | PS3AV_RESBIT_1920x1080P) | 295 | | PS3AV_RESBIT_1920x1080P) |
296 | #define PS3AV_RES_MASK_50 (PS3AV_RESBIT_720x576P \ | 296 | #define PS3AV_RES_MASK_50 (PS3AV_RESBIT_720x576P \ |
297 | | PS3AV_RESBIT_1280x720P \ | 297 | | PS3AV_RESBIT_1280x720P \ |
298 | | PS3AV_RESBIT_1920x1080I \ | 298 | | PS3AV_RESBIT_1920x1080I \ |
299 | | PS3AV_RESBIT_1920x1080P) | 299 | | PS3AV_RESBIT_1920x1080P) |
300 | 300 | ||
301 | /* for VESA automode */ | 301 | /* for VESA automode */ |
302 | #define PS3AV_RESBIT_VGA 0x0001 | 302 | #define PS3AV_RESBIT_VGA 0x0001 |
303 | #define PS3AV_RESBIT_WXGA 0x0002 | 303 | #define PS3AV_RESBIT_WXGA 0x0002 |
304 | #define PS3AV_RESBIT_SXGA 0x0004 | 304 | #define PS3AV_RESBIT_SXGA 0x0004 |
305 | #define PS3AV_RESBIT_WUXGA 0x0008 | 305 | #define PS3AV_RESBIT_WUXGA 0x0008 |
306 | #define PS3AV_RES_MASK_VESA (PS3AV_RESBIT_WXGA |\ | 306 | #define PS3AV_RES_MASK_VESA (PS3AV_RESBIT_WXGA |\ |
307 | PS3AV_RESBIT_SXGA |\ | 307 | PS3AV_RESBIT_SXGA |\ |
308 | PS3AV_RESBIT_WUXGA) | 308 | PS3AV_RESBIT_WUXGA) |
309 | 309 | ||
310 | #define PS3AV_MONITOR_TYPE_HDMI 1 /* HDMI */ | 310 | #define PS3AV_MONITOR_TYPE_HDMI 1 /* HDMI */ |
311 | #define PS3AV_MONITOR_TYPE_DVI 2 /* DVI */ | 311 | #define PS3AV_MONITOR_TYPE_DVI 2 /* DVI */ |
312 | 312 | ||
313 | 313 | ||
314 | /* for video mode */ | 314 | /* for video mode */ |
315 | enum ps3av_mode_num { | 315 | enum ps3av_mode_num { |
316 | PS3AV_MODE_AUTO = 0, | 316 | PS3AV_MODE_AUTO = 0, |
317 | PS3AV_MODE_480I = 1, | 317 | PS3AV_MODE_480I = 1, |
318 | PS3AV_MODE_480P = 2, | 318 | PS3AV_MODE_480P = 2, |
319 | PS3AV_MODE_720P60 = 3, | 319 | PS3AV_MODE_720P60 = 3, |
320 | PS3AV_MODE_1080I60 = 4, | 320 | PS3AV_MODE_1080I60 = 4, |
321 | PS3AV_MODE_1080P60 = 5, | 321 | PS3AV_MODE_1080P60 = 5, |
322 | PS3AV_MODE_576I = 6, | 322 | PS3AV_MODE_576I = 6, |
323 | PS3AV_MODE_576P = 7, | 323 | PS3AV_MODE_576P = 7, |
324 | PS3AV_MODE_720P50 = 8, | 324 | PS3AV_MODE_720P50 = 8, |
325 | PS3AV_MODE_1080I50 = 9, | 325 | PS3AV_MODE_1080I50 = 9, |
326 | PS3AV_MODE_1080P50 = 10, | 326 | PS3AV_MODE_1080P50 = 10, |
327 | PS3AV_MODE_WXGA = 11, | 327 | PS3AV_MODE_WXGA = 11, |
328 | PS3AV_MODE_SXGA = 12, | 328 | PS3AV_MODE_SXGA = 12, |
329 | PS3AV_MODE_WUXGA = 13, | 329 | PS3AV_MODE_WUXGA = 13, |
330 | }; | 330 | }; |
331 | 331 | ||
332 | #define PS3AV_MODE_MASK 0x000F | 332 | #define PS3AV_MODE_MASK 0x000F |
333 | #define PS3AV_MODE_HDCP_OFF 0x1000 /* Retail PS3 product doesn't support this */ | 333 | #define PS3AV_MODE_HDCP_OFF 0x1000 /* Retail PS3 product doesn't support this */ |
334 | #define PS3AV_MODE_DITHER 0x0800 | 334 | #define PS3AV_MODE_DITHER 0x0800 |
335 | #define PS3AV_MODE_COLOR 0x0400 | 335 | #define PS3AV_MODE_COLOR 0x0400 |
336 | #define PS3AV_MODE_WHITE 0x0200 | 336 | #define PS3AV_MODE_WHITE 0x0200 |
337 | #define PS3AV_MODE_FULL 0x0080 | 337 | #define PS3AV_MODE_FULL 0x0080 |
338 | #define PS3AV_MODE_DVI 0x0040 | 338 | #define PS3AV_MODE_DVI 0x0040 |
339 | #define PS3AV_MODE_RGB 0x0020 | 339 | #define PS3AV_MODE_RGB 0x0020 |
340 | 340 | ||
341 | 341 | ||
342 | #define PS3AV_DEFAULT_HDMI_MODE_ID_REG_60 PS3AV_MODE_480P | 342 | #define PS3AV_DEFAULT_HDMI_MODE_ID_REG_60 PS3AV_MODE_480P |
343 | #define PS3AV_DEFAULT_AVMULTI_MODE_ID_REG_60 PS3AV_MODE_480I | 343 | #define PS3AV_DEFAULT_AVMULTI_MODE_ID_REG_60 PS3AV_MODE_480I |
344 | #define PS3AV_DEFAULT_HDMI_MODE_ID_REG_50 PS3AV_MODE_576P | 344 | #define PS3AV_DEFAULT_HDMI_MODE_ID_REG_50 PS3AV_MODE_576P |
345 | #define PS3AV_DEFAULT_AVMULTI_MODE_ID_REG_50 PS3AV_MODE_576I | 345 | #define PS3AV_DEFAULT_AVMULTI_MODE_ID_REG_50 PS3AV_MODE_576I |
346 | 346 | ||
347 | #define PS3AV_REGION_60 0x01 | 347 | #define PS3AV_REGION_60 0x01 |
348 | #define PS3AV_REGION_50 0x02 | 348 | #define PS3AV_REGION_50 0x02 |
349 | #define PS3AV_REGION_RGB 0x10 | 349 | #define PS3AV_REGION_RGB 0x10 |
350 | 350 | ||
351 | #define get_status(buf) (((__u32 *)buf)[2]) | 351 | #define get_status(buf) (((__u32 *)buf)[2]) |
352 | #define PS3AV_HDR_SIZE 4 /* version + size */ | 352 | #define PS3AV_HDR_SIZE 4 /* version + size */ |
353 | 353 | ||
354 | 354 | ||
355 | /** command packet structure **/ | 355 | /** command packet structure **/ |
356 | struct ps3av_send_hdr { | 356 | struct ps3av_send_hdr { |
357 | u16 version; | 357 | u16 version; |
358 | u16 size; /* size of command packet */ | 358 | u16 size; /* size of command packet */ |
359 | u32 cid; /* command id */ | 359 | u32 cid; /* command id */ |
360 | }; | 360 | }; |
361 | 361 | ||
362 | struct ps3av_reply_hdr { | 362 | struct ps3av_reply_hdr { |
363 | u16 version; | 363 | u16 version; |
364 | u16 size; | 364 | u16 size; |
365 | u32 cid; | 365 | u32 cid; |
366 | u32 status; | 366 | u32 status; |
367 | }; | 367 | }; |
368 | 368 | ||
369 | /* backend: initialization */ | 369 | /* backend: initialization */ |
370 | struct ps3av_pkt_av_init { | 370 | struct ps3av_pkt_av_init { |
371 | struct ps3av_send_hdr send_hdr; | 371 | struct ps3av_send_hdr send_hdr; |
372 | u32 event_bit; | 372 | u32 event_bit; |
373 | }; | 373 | }; |
374 | 374 | ||
375 | /* backend: finalize */ | 375 | /* backend: finalize */ |
376 | struct ps3av_pkt_av_fin { | 376 | struct ps3av_pkt_av_fin { |
377 | struct ps3av_send_hdr send_hdr; | 377 | struct ps3av_send_hdr send_hdr; |
378 | /* recv */ | 378 | /* recv */ |
379 | u32 reserved; | 379 | u32 reserved; |
380 | }; | 380 | }; |
381 | 381 | ||
382 | /* backend: get port */ | 382 | /* backend: get port */ |
383 | struct ps3av_pkt_av_get_hw_conf { | 383 | struct ps3av_pkt_av_get_hw_conf { |
384 | struct ps3av_send_hdr send_hdr; | 384 | struct ps3av_send_hdr send_hdr; |
385 | /* recv */ | 385 | /* recv */ |
386 | u32 status; | 386 | u32 status; |
387 | u16 num_of_hdmi; /* out: number of hdmi */ | 387 | u16 num_of_hdmi; /* out: number of hdmi */ |
388 | u16 num_of_avmulti; /* out: number of avmulti */ | 388 | u16 num_of_avmulti; /* out: number of avmulti */ |
389 | u16 num_of_spdif; /* out: number of hdmi */ | 389 | u16 num_of_spdif; /* out: number of hdmi */ |
390 | u16 reserved; | 390 | u16 reserved; |
391 | }; | 391 | }; |
392 | 392 | ||
393 | /* backend: get monitor info */ | 393 | /* backend: get monitor info */ |
394 | struct ps3av_info_resolution { | 394 | struct ps3av_info_resolution { |
395 | u32 res_bits; | 395 | u32 res_bits; |
396 | u32 native; | 396 | u32 native; |
397 | }; | 397 | }; |
398 | 398 | ||
399 | struct ps3av_info_cs { | 399 | struct ps3av_info_cs { |
400 | u8 rgb; | 400 | u8 rgb; |
401 | u8 yuv444; | 401 | u8 yuv444; |
402 | u8 yuv422; | 402 | u8 yuv422; |
403 | u8 reserved; | 403 | u8 reserved; |
404 | }; | 404 | }; |
405 | 405 | ||
406 | struct ps3av_info_color { | 406 | struct ps3av_info_color { |
407 | u16 red_x; | 407 | u16 red_x; |
408 | u16 red_y; | 408 | u16 red_y; |
409 | u16 green_x; | 409 | u16 green_x; |
410 | u16 green_y; | 410 | u16 green_y; |
411 | u16 blue_x; | 411 | u16 blue_x; |
412 | u16 blue_y; | 412 | u16 blue_y; |
413 | u16 white_x; | 413 | u16 white_x; |
414 | u16 white_y; | 414 | u16 white_y; |
415 | u32 gamma; | 415 | u32 gamma; |
416 | }; | 416 | }; |
417 | 417 | ||
418 | struct ps3av_info_audio { | 418 | struct ps3av_info_audio { |
419 | u8 type; | 419 | u8 type; |
420 | u8 max_num_of_ch; | 420 | u8 max_num_of_ch; |
421 | u8 fs; | 421 | u8 fs; |
422 | u8 sbit; | 422 | u8 sbit; |
423 | }; | 423 | }; |
424 | 424 | ||
425 | struct ps3av_info_monitor { | 425 | struct ps3av_info_monitor { |
426 | u8 avport; | 426 | u8 avport; |
427 | u8 monitor_id[10]; | 427 | u8 monitor_id[10]; |
428 | u8 monitor_type; | 428 | u8 monitor_type; |
429 | u8 monitor_name[16]; | 429 | u8 monitor_name[16]; |
430 | struct ps3av_info_resolution res_60; | 430 | struct ps3av_info_resolution res_60; |
431 | struct ps3av_info_resolution res_50; | 431 | struct ps3av_info_resolution res_50; |
432 | struct ps3av_info_resolution res_other; | 432 | struct ps3av_info_resolution res_other; |
433 | struct ps3av_info_resolution res_vesa; | 433 | struct ps3av_info_resolution res_vesa; |
434 | struct ps3av_info_cs cs; | 434 | struct ps3av_info_cs cs; |
435 | struct ps3av_info_color color; | 435 | struct ps3av_info_color color; |
436 | u8 supported_ai; | 436 | u8 supported_ai; |
437 | u8 speaker_info; | 437 | u8 speaker_info; |
438 | u8 num_of_audio_block; | 438 | u8 num_of_audio_block; |
439 | struct ps3av_info_audio audio[0]; /* 0 or more audio blocks */ | 439 | struct ps3av_info_audio audio[0]; /* 0 or more audio blocks */ |
440 | u8 reserved[169]; | 440 | u8 reserved[169]; |
441 | } __attribute__ ((packed)); | 441 | } __attribute__ ((packed)); |
442 | 442 | ||
443 | struct ps3av_pkt_av_get_monitor_info { | 443 | struct ps3av_pkt_av_get_monitor_info { |
444 | struct ps3av_send_hdr send_hdr; | 444 | struct ps3av_send_hdr send_hdr; |
445 | u16 avport; /* in: avport */ | 445 | u16 avport; /* in: avport */ |
446 | u16 reserved; | 446 | u16 reserved; |
447 | /* recv */ | 447 | /* recv */ |
448 | struct ps3av_info_monitor info; /* out: monitor info */ | 448 | struct ps3av_info_monitor info; /* out: monitor info */ |
449 | }; | 449 | }; |
450 | 450 | ||
451 | /* backend: enable/disable event */ | 451 | /* backend: enable/disable event */ |
452 | struct ps3av_pkt_av_event { | 452 | struct ps3av_pkt_av_event { |
453 | struct ps3av_send_hdr send_hdr; | 453 | struct ps3av_send_hdr send_hdr; |
454 | u32 event_bit; /* in */ | 454 | u32 event_bit; /* in */ |
455 | }; | 455 | }; |
456 | 456 | ||
457 | /* backend: video cs param */ | 457 | /* backend: video cs param */ |
458 | struct ps3av_pkt_av_video_cs { | 458 | struct ps3av_pkt_av_video_cs { |
459 | struct ps3av_send_hdr send_hdr; | 459 | struct ps3av_send_hdr send_hdr; |
460 | u16 avport; /* in: avport */ | 460 | u16 avport; /* in: avport */ |
461 | u16 av_vid; /* in: video resolution */ | 461 | u16 av_vid; /* in: video resolution */ |
462 | u16 av_cs_out; /* in: output color space */ | 462 | u16 av_cs_out; /* in: output color space */ |
463 | u16 av_cs_in; /* in: input color space */ | 463 | u16 av_cs_in; /* in: input color space */ |
464 | u8 dither; /* in: dither bit length */ | 464 | u8 dither; /* in: dither bit length */ |
465 | u8 bitlen_out; /* in: bit length */ | 465 | u8 bitlen_out; /* in: bit length */ |
466 | u8 super_white; /* in: super white */ | 466 | u8 super_white; /* in: super white */ |
467 | u8 aspect; /* in: aspect ratio */ | 467 | u8 aspect; /* in: aspect ratio */ |
468 | }; | 468 | }; |
469 | 469 | ||
470 | /* backend: video mute */ | 470 | /* backend: video mute */ |
471 | struct ps3av_av_mute { | 471 | struct ps3av_av_mute { |
472 | u16 avport; /* in: avport */ | 472 | u16 avport; /* in: avport */ |
473 | u16 mute; /* in: mute on/off */ | 473 | u16 mute; /* in: mute on/off */ |
474 | }; | 474 | }; |
475 | 475 | ||
476 | struct ps3av_pkt_av_video_mute { | 476 | struct ps3av_pkt_av_video_mute { |
477 | struct ps3av_send_hdr send_hdr; | 477 | struct ps3av_send_hdr send_hdr; |
478 | struct ps3av_av_mute mute[PS3AV_MUTE_PORT_MAX]; | 478 | struct ps3av_av_mute mute[PS3AV_MUTE_PORT_MAX]; |
479 | }; | 479 | }; |
480 | 480 | ||
481 | /* backend: video disable signal */ | 481 | /* backend: video disable signal */ |
482 | struct ps3av_pkt_av_video_disable_sig { | 482 | struct ps3av_pkt_av_video_disable_sig { |
483 | struct ps3av_send_hdr send_hdr; | 483 | struct ps3av_send_hdr send_hdr; |
484 | u16 avport; /* in: avport */ | 484 | u16 avport; /* in: avport */ |
485 | u16 reserved; | 485 | u16 reserved; |
486 | }; | 486 | }; |
487 | 487 | ||
488 | /* backend: audio param */ | 488 | /* backend: audio param */ |
489 | struct ps3av_audio_info_frame { | 489 | struct ps3av_audio_info_frame { |
490 | struct pb1_bit { | 490 | struct pb1_bit { |
491 | u8 ct:4; | 491 | u8 ct:4; |
492 | u8 rsv:1; | 492 | u8 rsv:1; |
493 | u8 cc:3; | 493 | u8 cc:3; |
494 | } pb1; | 494 | } pb1; |
495 | struct pb2_bit { | 495 | struct pb2_bit { |
496 | u8 rsv:3; | 496 | u8 rsv:3; |
497 | u8 sf:3; | 497 | u8 sf:3; |
498 | u8 ss:2; | 498 | u8 ss:2; |
499 | } pb2; | 499 | } pb2; |
500 | u8 pb3; | 500 | u8 pb3; |
501 | u8 pb4; | 501 | u8 pb4; |
502 | struct pb5_bit { | 502 | struct pb5_bit { |
503 | u8 dm:1; | 503 | u8 dm:1; |
504 | u8 lsv:4; | 504 | u8 lsv:4; |
505 | u8 rsv:3; | 505 | u8 rsv:3; |
506 | } pb5; | 506 | } pb5; |
507 | }; | 507 | }; |
508 | 508 | ||
509 | struct ps3av_pkt_av_audio_param { | 509 | struct ps3av_pkt_av_audio_param { |
510 | struct ps3av_send_hdr send_hdr; | 510 | struct ps3av_send_hdr send_hdr; |
511 | u16 avport; /* in: avport */ | 511 | u16 avport; /* in: avport */ |
512 | u16 reserved; | 512 | u16 reserved; |
513 | u8 mclk; /* in: audio mclk */ | 513 | u8 mclk; /* in: audio mclk */ |
514 | u8 ns[3]; /* in: audio ns val */ | 514 | u8 ns[3]; /* in: audio ns val */ |
515 | u8 enable; /* in: audio enable */ | 515 | u8 enable; /* in: audio enable */ |
516 | u8 swaplr; /* in: audio swap */ | 516 | u8 swaplr; /* in: audio swap */ |
517 | u8 fifomap; /* in: audio fifomap */ | 517 | u8 fifomap; /* in: audio fifomap */ |
518 | u8 inputctrl; /* in: audio input ctrl */ | 518 | u8 inputctrl; /* in: audio input ctrl */ |
519 | u8 inputlen; /* in: sample bit size */ | 519 | u8 inputlen; /* in: sample bit size */ |
520 | u8 layout; /* in: speaker layout param */ | 520 | u8 layout; /* in: speaker layout param */ |
521 | struct ps3av_audio_info_frame info; /* in: info */ | 521 | struct ps3av_audio_info_frame info; /* in: info */ |
522 | u8 chstat[5]; /* in: ch stat */ | 522 | u8 chstat[5]; /* in: ch stat */ |
523 | }; | 523 | }; |
524 | 524 | ||
525 | /* backend: audio_mute */ | 525 | /* backend: audio_mute */ |
526 | struct ps3av_pkt_av_audio_mute { | 526 | struct ps3av_pkt_av_audio_mute { |
527 | struct ps3av_send_hdr send_hdr; | 527 | struct ps3av_send_hdr send_hdr; |
528 | struct ps3av_av_mute mute[PS3AV_MUTE_PORT_MAX]; | 528 | struct ps3av_av_mute mute[PS3AV_MUTE_PORT_MAX]; |
529 | }; | 529 | }; |
530 | 530 | ||
531 | /* backend: hdmi_mode */ | 531 | /* backend: hdmi_mode */ |
532 | struct ps3av_pkt_av_hdmi_mode { | 532 | struct ps3av_pkt_av_hdmi_mode { |
533 | struct ps3av_send_hdr send_hdr; | 533 | struct ps3av_send_hdr send_hdr; |
534 | u8 mode; /* in: hdmi_mode */ | 534 | u8 mode; /* in: hdmi_mode */ |
535 | u8 reserved0; | 535 | u8 reserved0; |
536 | u8 reserved1; | 536 | u8 reserved1; |
537 | u8 reserved2; | 537 | u8 reserved2; |
538 | }; | 538 | }; |
539 | 539 | ||
540 | /* backend: tv_mute */ | 540 | /* backend: tv_mute */ |
541 | struct ps3av_pkt_av_tv_mute { | 541 | struct ps3av_pkt_av_tv_mute { |
542 | struct ps3av_send_hdr send_hdr; | 542 | struct ps3av_send_hdr send_hdr; |
543 | u16 avport; /* in: avport HDMI only */ | 543 | u16 avport; /* in: avport HDMI only */ |
544 | u16 mute; /* in: mute */ | 544 | u16 mute; /* in: mute */ |
545 | }; | 545 | }; |
546 | 546 | ||
547 | /* video: initialize */ | 547 | /* video: initialize */ |
548 | struct ps3av_pkt_video_init { | 548 | struct ps3av_pkt_video_init { |
549 | struct ps3av_send_hdr send_hdr; | 549 | struct ps3av_send_hdr send_hdr; |
550 | /* recv */ | 550 | /* recv */ |
551 | u32 reserved; | 551 | u32 reserved; |
552 | }; | 552 | }; |
553 | 553 | ||
554 | /* video: mode setting */ | 554 | /* video: mode setting */ |
555 | struct ps3av_pkt_video_mode { | 555 | struct ps3av_pkt_video_mode { |
556 | struct ps3av_send_hdr send_hdr; | 556 | struct ps3av_send_hdr send_hdr; |
557 | u32 video_head; /* in: head */ | 557 | u32 video_head; /* in: head */ |
558 | u32 reserved; | 558 | u32 reserved; |
559 | u32 video_vid; /* in: video resolution */ | 559 | u32 video_vid; /* in: video resolution */ |
560 | u16 reserved1; | 560 | u16 reserved1; |
561 | u16 width; /* in: width in pixel */ | 561 | u16 width; /* in: width in pixel */ |
562 | u16 reserved2; | 562 | u16 reserved2; |
563 | u16 height; /* in: height in pixel */ | 563 | u16 height; /* in: height in pixel */ |
564 | u32 pitch; /* in: line size in byte */ | 564 | u32 pitch; /* in: line size in byte */ |
565 | u32 video_out_format; /* in: out format */ | 565 | u32 video_out_format; /* in: out format */ |
566 | u32 video_format; /* in: input frame buffer format */ | 566 | u32 video_format; /* in: input frame buffer format */ |
567 | u8 reserved3; | 567 | u8 reserved3; |
568 | u8 video_cl_cnv; /* in: color conversion */ | 568 | u8 video_cl_cnv; /* in: color conversion */ |
569 | u16 video_order; /* in: input RGB order */ | 569 | u16 video_order; /* in: input RGB order */ |
570 | u32 reserved4; | 570 | u32 reserved4; |
571 | }; | 571 | }; |
572 | 572 | ||
573 | /* video: format */ | 573 | /* video: format */ |
574 | struct ps3av_pkt_video_format { | 574 | struct ps3av_pkt_video_format { |
575 | struct ps3av_send_hdr send_hdr; | 575 | struct ps3av_send_hdr send_hdr; |
576 | u32 video_head; /* in: head */ | 576 | u32 video_head; /* in: head */ |
577 | u32 video_format; /* in: frame buffer format */ | 577 | u32 video_format; /* in: frame buffer format */ |
578 | u8 reserved; | 578 | u8 reserved; |
579 | u8 video_cl_cnv; /* in: color conversion */ | 579 | u8 video_cl_cnv; /* in: color conversion */ |
580 | u16 video_order; /* in: input RGB order */ | 580 | u16 video_order; /* in: input RGB order */ |
581 | }; | 581 | }; |
582 | 582 | ||
583 | /* video: pitch */ | 583 | /* video: pitch */ |
584 | struct ps3av_pkt_video_pitch { | 584 | struct ps3av_pkt_video_pitch { |
585 | u16 version; | 585 | u16 version; |
586 | u16 size; /* size of command packet */ | 586 | u16 size; /* size of command packet */ |
587 | u32 cid; /* command id */ | 587 | u32 cid; /* command id */ |
588 | u32 video_head; /* in: head */ | 588 | u32 video_head; /* in: head */ |
589 | u32 pitch; /* in: line size in byte */ | 589 | u32 pitch; /* in: line size in byte */ |
590 | }; | 590 | }; |
591 | 591 | ||
592 | /* audio: initialize */ | 592 | /* audio: initialize */ |
593 | struct ps3av_pkt_audio_init { | 593 | struct ps3av_pkt_audio_init { |
594 | struct ps3av_send_hdr send_hdr; | 594 | struct ps3av_send_hdr send_hdr; |
595 | /* recv */ | 595 | /* recv */ |
596 | u32 reserved; | 596 | u32 reserved; |
597 | }; | 597 | }; |
598 | 598 | ||
599 | /* audio: mode setting */ | 599 | /* audio: mode setting */ |
600 | struct ps3av_pkt_audio_mode { | 600 | struct ps3av_pkt_audio_mode { |
601 | struct ps3av_send_hdr send_hdr; | 601 | struct ps3av_send_hdr send_hdr; |
602 | u8 avport; /* in: avport */ | 602 | u8 avport; /* in: avport */ |
603 | u8 reserved0[3]; | 603 | u8 reserved0[3]; |
604 | u32 mask; /* in: mask */ | 604 | u32 mask; /* in: mask */ |
605 | u32 audio_num_of_ch; /* in: number of ch */ | 605 | u32 audio_num_of_ch; /* in: number of ch */ |
606 | u32 audio_fs; /* in: sampling freq */ | 606 | u32 audio_fs; /* in: sampling freq */ |
607 | u32 audio_word_bits; /* in: sample bit size */ | 607 | u32 audio_word_bits; /* in: sample bit size */ |
608 | u32 audio_format; /* in: audio output format */ | 608 | u32 audio_format; /* in: audio output format */ |
609 | u32 audio_source; /* in: audio source */ | 609 | u32 audio_source; /* in: audio source */ |
610 | u8 audio_enable[4]; /* in: audio enable */ | 610 | u8 audio_enable[4]; /* in: audio enable */ |
611 | u8 audio_swap[4]; /* in: audio swap */ | 611 | u8 audio_swap[4]; /* in: audio swap */ |
612 | u8 audio_map[4]; /* in: audio map */ | 612 | u8 audio_map[4]; /* in: audio map */ |
613 | u32 audio_layout; /* in: speaker layout */ | 613 | u32 audio_layout; /* in: speaker layout */ |
614 | u32 audio_downmix; /* in: audio downmix permission */ | 614 | u32 audio_downmix; /* in: audio downmix permission */ |
615 | u32 audio_downmix_level; | 615 | u32 audio_downmix_level; |
616 | u8 audio_cs_info[8]; /* in: IEC channel status */ | 616 | u8 audio_cs_info[8]; /* in: IEC channel status */ |
617 | }; | 617 | }; |
618 | 618 | ||
619 | /* audio: mute */ | 619 | /* audio: mute */ |
620 | struct ps3av_audio_mute { | 620 | struct ps3av_audio_mute { |
621 | u8 avport; /* in: opt_port optical */ | 621 | u8 avport; /* in: opt_port optical */ |
622 | u8 reserved[3]; | 622 | u8 reserved[3]; |
623 | u32 mute; /* in: mute */ | 623 | u32 mute; /* in: mute */ |
624 | }; | 624 | }; |
625 | 625 | ||
626 | struct ps3av_pkt_audio_mute { | 626 | struct ps3av_pkt_audio_mute { |
627 | struct ps3av_send_hdr send_hdr; | 627 | struct ps3av_send_hdr send_hdr; |
628 | struct ps3av_audio_mute mute[PS3AV_OPT_PORT_MAX]; | 628 | struct ps3av_audio_mute mute[PS3AV_OPT_PORT_MAX]; |
629 | }; | 629 | }; |
630 | 630 | ||
631 | /* audio: active/inactive */ | 631 | /* audio: active/inactive */ |
632 | struct ps3av_pkt_audio_active { | 632 | struct ps3av_pkt_audio_active { |
633 | struct ps3av_send_hdr send_hdr; | 633 | struct ps3av_send_hdr send_hdr; |
634 | u32 audio_port; /* in: audio active/inactive port */ | 634 | u32 audio_port; /* in: audio active/inactive port */ |
635 | }; | 635 | }; |
636 | 636 | ||
637 | /* audio: SPDIF user bit */ | 637 | /* audio: SPDIF user bit */ |
638 | struct ps3av_pkt_audio_spdif_bit { | 638 | struct ps3av_pkt_audio_spdif_bit { |
639 | u16 version; | 639 | u16 version; |
640 | u16 size; /* size of command packet */ | 640 | u16 size; /* size of command packet */ |
641 | u32 cid; /* command id */ | 641 | u32 cid; /* command id */ |
642 | u8 avport; /* in: avport SPDIF only */ | 642 | u8 avport; /* in: avport SPDIF only */ |
643 | u8 reserved[3]; | 643 | u8 reserved[3]; |
644 | u32 audio_port; /* in: SPDIF only */ | 644 | u32 audio_port; /* in: SPDIF only */ |
645 | u32 spdif_bit_data[12]; /* in: user bit data */ | 645 | u32 spdif_bit_data[12]; /* in: user bit data */ |
646 | }; | 646 | }; |
647 | 647 | ||
648 | /* audio: audio control */ | 648 | /* audio: audio control */ |
649 | struct ps3av_pkt_audio_ctrl { | 649 | struct ps3av_pkt_audio_ctrl { |
650 | u16 version; | 650 | u16 version; |
651 | u16 size; /* size of command packet */ | 651 | u16 size; /* size of command packet */ |
652 | u32 cid; /* command id */ | 652 | u32 cid; /* command id */ |
653 | u32 audio_ctrl_id; /* in: control id */ | 653 | u32 audio_ctrl_id; /* in: control id */ |
654 | u32 audio_ctrl_data[4]; /* in: control data */ | 654 | u32 audio_ctrl_data[4]; /* in: control data */ |
655 | }; | 655 | }; |
656 | 656 | ||
657 | /* avb:param */ | 657 | /* avb:param */ |
658 | #define PS3AV_PKT_AVB_PARAM_MAX_BUF_SIZE \ | 658 | #define PS3AV_PKT_AVB_PARAM_MAX_BUF_SIZE \ |
659 | (PS3AV_AVB_NUM_VIDEO*sizeof(struct ps3av_pkt_video_mode) + \ | 659 | (PS3AV_AVB_NUM_VIDEO*sizeof(struct ps3av_pkt_video_mode) + \ |
660 | PS3AV_AVB_NUM_AUDIO*sizeof(struct ps3av_pkt_audio_mode) + \ | 660 | PS3AV_AVB_NUM_AUDIO*sizeof(struct ps3av_pkt_audio_mode) + \ |
661 | PS3AV_AVB_NUM_AV_VIDEO*sizeof(struct ps3av_pkt_av_video_cs) + \ | 661 | PS3AV_AVB_NUM_AV_VIDEO*sizeof(struct ps3av_pkt_av_video_cs) + \ |
662 | PS3AV_AVB_NUM_AV_AUDIO*sizeof(struct ps3av_pkt_av_audio_param)) | 662 | PS3AV_AVB_NUM_AV_AUDIO*sizeof(struct ps3av_pkt_av_audio_param)) |
663 | 663 | ||
664 | struct ps3av_pkt_avb_param { | 664 | struct ps3av_pkt_avb_param { |
665 | struct ps3av_send_hdr send_hdr; | 665 | struct ps3av_send_hdr send_hdr; |
666 | u16 num_of_video_pkt; | 666 | u16 num_of_video_pkt; |
667 | u16 num_of_audio_pkt; | 667 | u16 num_of_audio_pkt; |
668 | u16 num_of_av_video_pkt; | 668 | u16 num_of_av_video_pkt; |
669 | u16 num_of_av_audio_pkt; | 669 | u16 num_of_av_audio_pkt; |
670 | /* | 670 | /* |
671 | * The actual buffer layout depends on the fields above: | 671 | * The actual buffer layout depends on the fields above: |
672 | * | 672 | * |
673 | * struct ps3av_pkt_video_mode video[num_of_video_pkt]; | 673 | * struct ps3av_pkt_video_mode video[num_of_video_pkt]; |
674 | * struct ps3av_pkt_audio_mode audio[num_of_audio_pkt]; | 674 | * struct ps3av_pkt_audio_mode audio[num_of_audio_pkt]; |
675 | * struct ps3av_pkt_av_video_cs av_video[num_of_av_video_pkt]; | 675 | * struct ps3av_pkt_av_video_cs av_video[num_of_av_video_pkt]; |
676 | * struct ps3av_pkt_av_audio_param av_audio[num_of_av_audio_pkt]; | 676 | * struct ps3av_pkt_av_audio_param av_audio[num_of_av_audio_pkt]; |
677 | */ | 677 | */ |
678 | u8 buf[PS3AV_PKT_AVB_PARAM_MAX_BUF_SIZE]; | 678 | u8 buf[PS3AV_PKT_AVB_PARAM_MAX_BUF_SIZE]; |
679 | }; | 679 | }; |
680 | 680 | ||
681 | /* channel status */ | 681 | /* channel status */ |
682 | extern u8 ps3av_mode_cs_info[]; | 682 | extern u8 ps3av_mode_cs_info[]; |
683 | 683 | ||
684 | /** command status **/ | 684 | /** command status **/ |
685 | #define PS3AV_STATUS_SUCCESS 0x0000 /* success */ | 685 | #define PS3AV_STATUS_SUCCESS 0x0000 /* success */ |
686 | #define PS3AV_STATUS_RECEIVE_VUART_ERROR 0x0001 /* receive vuart error */ | 686 | #define PS3AV_STATUS_RECEIVE_VUART_ERROR 0x0001 /* receive vuart error */ |
687 | #define PS3AV_STATUS_SYSCON_COMMUNICATE_FAIL 0x0002 /* syscon communication error */ | 687 | #define PS3AV_STATUS_SYSCON_COMMUNICATE_FAIL 0x0002 /* syscon communication error */ |
688 | #define PS3AV_STATUS_INVALID_COMMAND 0x0003 /* obsolete invalid CID */ | 688 | #define PS3AV_STATUS_INVALID_COMMAND 0x0003 /* obsolete invalid CID */ |
689 | #define PS3AV_STATUS_INVALID_PORT 0x0004 /* invalid port number */ | 689 | #define PS3AV_STATUS_INVALID_PORT 0x0004 /* invalid port number */ |
690 | #define PS3AV_STATUS_INVALID_VID 0x0005 /* invalid video format */ | 690 | #define PS3AV_STATUS_INVALID_VID 0x0005 /* invalid video format */ |
691 | #define PS3AV_STATUS_INVALID_COLOR_SPACE 0x0006 /* invalid video colose space */ | 691 | #define PS3AV_STATUS_INVALID_COLOR_SPACE 0x0006 /* invalid video colose space */ |
692 | #define PS3AV_STATUS_INVALID_FS 0x0007 /* invalid audio sampling freq */ | 692 | #define PS3AV_STATUS_INVALID_FS 0x0007 /* invalid audio sampling freq */ |
693 | #define PS3AV_STATUS_INVALID_AUDIO_CH 0x0008 /* invalid audio channel number */ | 693 | #define PS3AV_STATUS_INVALID_AUDIO_CH 0x0008 /* invalid audio channel number */ |
694 | #define PS3AV_STATUS_UNSUPPORTED_VERSION 0x0009 /* version mismatch */ | 694 | #define PS3AV_STATUS_UNSUPPORTED_VERSION 0x0009 /* version mismatch */ |
695 | #define PS3AV_STATUS_INVALID_SAMPLE_SIZE 0x000a /* invalid audio sample bit size */ | 695 | #define PS3AV_STATUS_INVALID_SAMPLE_SIZE 0x000a /* invalid audio sample bit size */ |
696 | #define PS3AV_STATUS_FAILURE 0x000b /* other failures */ | 696 | #define PS3AV_STATUS_FAILURE 0x000b /* other failures */ |
697 | #define PS3AV_STATUS_UNSUPPORTED_COMMAND 0x000c /* unsupported cid */ | 697 | #define PS3AV_STATUS_UNSUPPORTED_COMMAND 0x000c /* unsupported cid */ |
698 | #define PS3AV_STATUS_BUFFER_OVERFLOW 0x000d /* write buffer overflow */ | 698 | #define PS3AV_STATUS_BUFFER_OVERFLOW 0x000d /* write buffer overflow */ |
699 | #define PS3AV_STATUS_INVALID_VIDEO_PARAM 0x000e /* invalid video param */ | 699 | #define PS3AV_STATUS_INVALID_VIDEO_PARAM 0x000e /* invalid video param */ |
700 | #define PS3AV_STATUS_NO_SEL 0x000f /* not exist selector */ | 700 | #define PS3AV_STATUS_NO_SEL 0x000f /* not exist selector */ |
701 | #define PS3AV_STATUS_INVALID_AV_PARAM 0x0010 /* invalid backend param */ | 701 | #define PS3AV_STATUS_INVALID_AV_PARAM 0x0010 /* invalid backend param */ |
702 | #define PS3AV_STATUS_INVALID_AUDIO_PARAM 0x0011 /* invalid audio param */ | 702 | #define PS3AV_STATUS_INVALID_AUDIO_PARAM 0x0011 /* invalid audio param */ |
703 | #define PS3AV_STATUS_UNSUPPORTED_HDMI_MODE 0x0012 /* unsupported hdmi mode */ | 703 | #define PS3AV_STATUS_UNSUPPORTED_HDMI_MODE 0x0012 /* unsupported hdmi mode */ |
704 | #define PS3AV_STATUS_NO_SYNC_HEAD 0x0013 /* sync head failed */ | 704 | #define PS3AV_STATUS_NO_SYNC_HEAD 0x0013 /* sync head failed */ |
705 | 705 | ||
706 | extern void ps3av_set_hdr(u32, u16, struct ps3av_send_hdr *); | 706 | extern void ps3av_set_hdr(u32, u16, struct ps3av_send_hdr *); |
707 | extern int ps3av_do_pkt(u32, u16, size_t, struct ps3av_send_hdr *); | 707 | extern int ps3av_do_pkt(u32, u16, size_t, struct ps3av_send_hdr *); |
708 | 708 | ||
709 | extern int ps3av_cmd_init(void); | 709 | extern int ps3av_cmd_init(void); |
710 | extern int ps3av_cmd_fin(void); | 710 | extern int ps3av_cmd_fin(void); |
711 | extern int ps3av_cmd_av_video_mute(int, u32 *, u32); | 711 | extern int ps3av_cmd_av_video_mute(int, u32 *, u32); |
712 | extern int ps3av_cmd_av_video_disable_sig(u32); | 712 | extern int ps3av_cmd_av_video_disable_sig(u32); |
713 | extern int ps3av_cmd_av_tv_mute(u32, u32); | 713 | extern int ps3av_cmd_av_tv_mute(u32, u32); |
714 | extern int ps3av_cmd_enable_event(void); | 714 | extern int ps3av_cmd_enable_event(void); |
715 | extern int ps3av_cmd_av_hdmi_mode(u8); | 715 | extern int ps3av_cmd_av_hdmi_mode(u8); |
716 | extern u32 ps3av_cmd_set_av_video_cs(void *, u32, int, int, int, u32); | 716 | extern u32 ps3av_cmd_set_av_video_cs(void *, u32, int, int, int, u32); |
717 | extern u32 ps3av_cmd_set_video_mode(void *, u32, int, int, u32); | 717 | extern u32 ps3av_cmd_set_video_mode(void *, u32, int, int, u32); |
718 | extern int ps3av_cmd_video_format_black(u32, u32, u32); | 718 | extern int ps3av_cmd_video_format_black(u32, u32, u32); |
719 | extern int ps3av_cmd_av_audio_mute(int, u32 *, u32); | 719 | extern int ps3av_cmd_av_audio_mute(int, u32 *, u32); |
720 | extern u32 ps3av_cmd_set_av_audio_param(void *, u32, | 720 | extern u32 ps3av_cmd_set_av_audio_param(void *, u32, |
721 | const struct ps3av_pkt_audio_mode *, | 721 | const struct ps3av_pkt_audio_mode *, |
722 | u32); | 722 | u32); |
723 | extern void ps3av_cmd_set_audio_mode(struct ps3av_pkt_audio_mode *, u32, u32, | 723 | extern void ps3av_cmd_set_audio_mode(struct ps3av_pkt_audio_mode *, u32, u32, |
724 | u32, u32, u32, u32); | 724 | u32, u32, u32, u32); |
725 | extern int ps3av_cmd_audio_mode(struct ps3av_pkt_audio_mode *); | 725 | extern int ps3av_cmd_audio_mode(struct ps3av_pkt_audio_mode *); |
726 | extern int ps3av_cmd_audio_mute(int, u32 *, u32); | 726 | extern int ps3av_cmd_audio_mute(int, u32 *, u32); |
727 | extern int ps3av_cmd_audio_active(int, u32); | 727 | extern int ps3av_cmd_audio_active(int, u32); |
728 | extern int ps3av_cmd_avb_param(struct ps3av_pkt_avb_param *, u32); | 728 | extern int ps3av_cmd_avb_param(struct ps3av_pkt_avb_param *, u32); |
729 | extern int ps3av_cmd_av_get_hw_conf(struct ps3av_pkt_av_get_hw_conf *); | 729 | extern int ps3av_cmd_av_get_hw_conf(struct ps3av_pkt_av_get_hw_conf *); |
730 | extern int ps3av_cmd_video_get_monitor_info(struct ps3av_pkt_av_get_monitor_info *, | 730 | extern int ps3av_cmd_video_get_monitor_info(struct ps3av_pkt_av_get_monitor_info *, |
731 | u32); | 731 | u32); |
732 | 732 | ||
733 | extern int ps3av_set_video_mode(u32); | 733 | extern int ps3av_set_video_mode(u32); |
734 | extern int ps3av_set_audio_mode(u32, u32, u32, u32, u32); | 734 | extern int ps3av_set_audio_mode(u32, u32, u32, u32, u32); |
735 | extern int ps3av_get_auto_mode(void); | 735 | extern int ps3av_get_auto_mode(void); |
736 | extern int ps3av_get_mode(void); | 736 | extern int ps3av_get_mode(void); |
737 | extern int ps3av_video_mode2res(u32, u32 *, u32 *); | 737 | extern int ps3av_video_mode2res(u32, u32 *, u32 *); |
738 | extern int ps3av_video_mute(int); | 738 | extern int ps3av_video_mute(int); |
739 | extern int ps3av_audio_mute(int); | 739 | extern int ps3av_audio_mute(int); |
740 | extern int ps3av_audio_mute_analog(int); | 740 | extern int ps3av_audio_mute_analog(int); |
741 | extern int ps3av_dev_open(void); | 741 | extern int ps3av_dev_open(void); |
742 | extern int ps3av_dev_close(void); | 742 | extern int ps3av_dev_close(void); |
743 | extern void ps3av_register_flip_ctl(void (*flip_ctl)(int on, void *data), | ||
744 | void *flip_data); | ||
745 | extern void ps3av_flip_ctl(int on); | ||
746 | |||
747 | #endif /* _ASM_POWERPC_PS3AV_H_ */ | 743 | #endif /* _ASM_POWERPC_PS3AV_H_ */ |
748 | 744 |
arch/powerpc/platforms/ps3/setup.c
1 | /* | 1 | /* |
2 | * PS3 platform setup routines. | 2 | * PS3 platform setup routines. |
3 | * | 3 | * |
4 | * Copyright (C) 2006 Sony Computer Entertainment Inc. | 4 | * Copyright (C) 2006 Sony Computer Entertainment Inc. |
5 | * Copyright 2006 Sony Corp. | 5 | * Copyright 2006 Sony Corp. |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License as published by | 8 | * it under the terms of the GNU General Public License as published by |
9 | * the Free Software Foundation; version 2 of the License. | 9 | * the Free Software Foundation; version 2 of the License. |
10 | * | 10 | * |
11 | * This program is distributed in the hope that it will be useful, | 11 | * This program is distributed in the hope that it will be useful, |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | * GNU General Public License for more details. | 14 | * GNU General Public License for more details. |
15 | * | 15 | * |
16 | * You should have received a copy of the GNU General Public License | 16 | * You should have received a copy of the GNU General Public License |
17 | * along with this program; if not, write to the Free Software | 17 | * along with this program; if not, write to the Free Software |
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
19 | */ | 19 | */ |
20 | 20 | ||
21 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
22 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
23 | #include <linux/fs.h> | 23 | #include <linux/fs.h> |
24 | #include <linux/root_dev.h> | 24 | #include <linux/root_dev.h> |
25 | #include <linux/console.h> | 25 | #include <linux/console.h> |
26 | #include <linux/kexec.h> | 26 | #include <linux/kexec.h> |
27 | #include <linux/bootmem.h> | 27 | #include <linux/bootmem.h> |
28 | 28 | ||
29 | #include <asm/machdep.h> | 29 | #include <asm/machdep.h> |
30 | #include <asm/firmware.h> | 30 | #include <asm/firmware.h> |
31 | #include <asm/time.h> | 31 | #include <asm/time.h> |
32 | #include <asm/iommu.h> | 32 | #include <asm/iommu.h> |
33 | #include <asm/udbg.h> | 33 | #include <asm/udbg.h> |
34 | #include <asm/prom.h> | 34 | #include <asm/prom.h> |
35 | #include <asm/lv1call.h> | 35 | #include <asm/lv1call.h> |
36 | 36 | ||
37 | #include "platform.h" | 37 | #include "platform.h" |
38 | 38 | ||
39 | #if defined(DEBUG) | 39 | #if defined(DEBUG) |
40 | #define DBG udbg_printf | 40 | #define DBG udbg_printf |
41 | #else | 41 | #else |
42 | #define DBG pr_debug | 42 | #define DBG pr_debug |
43 | #endif | 43 | #endif |
44 | 44 | ||
45 | /* mutex synchronizing GPU accesses and video mode changes */ | ||
46 | DEFINE_MUTEX(ps3_gpu_mutex); | ||
47 | EXPORT_SYMBOL_GPL(ps3_gpu_mutex); | ||
48 | |||
45 | #if !defined(CONFIG_SMP) | 49 | #if !defined(CONFIG_SMP) |
46 | static void smp_send_stop(void) {} | 50 | static void smp_send_stop(void) {} |
47 | #endif | 51 | #endif |
48 | 52 | ||
49 | static union ps3_firmware_version ps3_firmware_version; | 53 | static union ps3_firmware_version ps3_firmware_version; |
50 | 54 | ||
51 | void ps3_get_firmware_version(union ps3_firmware_version *v) | 55 | void ps3_get_firmware_version(union ps3_firmware_version *v) |
52 | { | 56 | { |
53 | *v = ps3_firmware_version; | 57 | *v = ps3_firmware_version; |
54 | } | 58 | } |
55 | EXPORT_SYMBOL_GPL(ps3_get_firmware_version); | 59 | EXPORT_SYMBOL_GPL(ps3_get_firmware_version); |
56 | 60 | ||
57 | int ps3_compare_firmware_version(u16 major, u16 minor, u16 rev) | 61 | int ps3_compare_firmware_version(u16 major, u16 minor, u16 rev) |
58 | { | 62 | { |
59 | union ps3_firmware_version x; | 63 | union ps3_firmware_version x; |
60 | 64 | ||
61 | x.pad = 0; | 65 | x.pad = 0; |
62 | x.major = major; | 66 | x.major = major; |
63 | x.minor = minor; | 67 | x.minor = minor; |
64 | x.rev = rev; | 68 | x.rev = rev; |
65 | 69 | ||
66 | return (ps3_firmware_version.raw > x.raw) - | 70 | return (ps3_firmware_version.raw > x.raw) - |
67 | (ps3_firmware_version.raw < x.raw); | 71 | (ps3_firmware_version.raw < x.raw); |
68 | } | 72 | } |
69 | EXPORT_SYMBOL_GPL(ps3_compare_firmware_version); | 73 | EXPORT_SYMBOL_GPL(ps3_compare_firmware_version); |
70 | 74 | ||
71 | static void ps3_power_save(void) | 75 | static void ps3_power_save(void) |
72 | { | 76 | { |
73 | /* | 77 | /* |
74 | * lv1_pause() puts the PPE thread into inactive state until an | 78 | * lv1_pause() puts the PPE thread into inactive state until an |
75 | * irq on an unmasked plug exists. MSR[EE] has no effect. | 79 | * irq on an unmasked plug exists. MSR[EE] has no effect. |
76 | * flags: 0 = wake on DEC interrupt, 1 = ignore DEC interrupt. | 80 | * flags: 0 = wake on DEC interrupt, 1 = ignore DEC interrupt. |
77 | */ | 81 | */ |
78 | 82 | ||
79 | lv1_pause(0); | 83 | lv1_pause(0); |
80 | } | 84 | } |
81 | 85 | ||
82 | static void ps3_restart(char *cmd) | 86 | static void ps3_restart(char *cmd) |
83 | { | 87 | { |
84 | DBG("%s:%d cmd '%s'\n", __func__, __LINE__, cmd); | 88 | DBG("%s:%d cmd '%s'\n", __func__, __LINE__, cmd); |
85 | 89 | ||
86 | smp_send_stop(); | 90 | smp_send_stop(); |
87 | ps3_sys_manager_restart(); /* never returns */ | 91 | ps3_sys_manager_restart(); /* never returns */ |
88 | } | 92 | } |
89 | 93 | ||
90 | static void ps3_power_off(void) | 94 | static void ps3_power_off(void) |
91 | { | 95 | { |
92 | DBG("%s:%d\n", __func__, __LINE__); | 96 | DBG("%s:%d\n", __func__, __LINE__); |
93 | 97 | ||
94 | smp_send_stop(); | 98 | smp_send_stop(); |
95 | ps3_sys_manager_power_off(); /* never returns */ | 99 | ps3_sys_manager_power_off(); /* never returns */ |
96 | } | 100 | } |
97 | 101 | ||
98 | static void ps3_halt(void) | 102 | static void ps3_halt(void) |
99 | { | 103 | { |
100 | DBG("%s:%d\n", __func__, __LINE__); | 104 | DBG("%s:%d\n", __func__, __LINE__); |
101 | 105 | ||
102 | smp_send_stop(); | 106 | smp_send_stop(); |
103 | ps3_sys_manager_halt(); /* never returns */ | 107 | ps3_sys_manager_halt(); /* never returns */ |
104 | } | 108 | } |
105 | 109 | ||
106 | static void ps3_panic(char *str) | 110 | static void ps3_panic(char *str) |
107 | { | 111 | { |
108 | DBG("%s:%d %s\n", __func__, __LINE__, str); | 112 | DBG("%s:%d %s\n", __func__, __LINE__, str); |
109 | 113 | ||
110 | smp_send_stop(); | 114 | smp_send_stop(); |
111 | printk("\n"); | 115 | printk("\n"); |
112 | printk(" System does not reboot automatically.\n"); | 116 | printk(" System does not reboot automatically.\n"); |
113 | printk(" Please press POWER button.\n"); | 117 | printk(" Please press POWER button.\n"); |
114 | printk("\n"); | 118 | printk("\n"); |
115 | 119 | ||
116 | while(1) | 120 | while(1) |
117 | lv1_pause(1); | 121 | lv1_pause(1); |
118 | } | 122 | } |
119 | 123 | ||
120 | #if defined(CONFIG_FB_PS3) || defined(CONFIG_FB_PS3_MODULE) || \ | 124 | #if defined(CONFIG_FB_PS3) || defined(CONFIG_FB_PS3_MODULE) || \ |
121 | defined(CONFIG_PS3_FLASH) || defined(CONFIG_PS3_FLASH_MODULE) | 125 | defined(CONFIG_PS3_FLASH) || defined(CONFIG_PS3_FLASH_MODULE) |
122 | static void __init prealloc(struct ps3_prealloc *p) | 126 | static void __init prealloc(struct ps3_prealloc *p) |
123 | { | 127 | { |
124 | if (!p->size) | 128 | if (!p->size) |
125 | return; | 129 | return; |
126 | 130 | ||
127 | p->address = __alloc_bootmem(p->size, p->align, __pa(MAX_DMA_ADDRESS)); | 131 | p->address = __alloc_bootmem(p->size, p->align, __pa(MAX_DMA_ADDRESS)); |
128 | if (!p->address) { | 132 | if (!p->address) { |
129 | printk(KERN_ERR "%s: Cannot allocate %s\n", __func__, | 133 | printk(KERN_ERR "%s: Cannot allocate %s\n", __func__, |
130 | p->name); | 134 | p->name); |
131 | return; | 135 | return; |
132 | } | 136 | } |
133 | 137 | ||
134 | printk(KERN_INFO "%s: %lu bytes at %p\n", p->name, p->size, | 138 | printk(KERN_INFO "%s: %lu bytes at %p\n", p->name, p->size, |
135 | p->address); | 139 | p->address); |
136 | } | 140 | } |
137 | #endif | 141 | #endif |
138 | 142 | ||
139 | #if defined(CONFIG_FB_PS3) || defined(CONFIG_FB_PS3_MODULE) | 143 | #if defined(CONFIG_FB_PS3) || defined(CONFIG_FB_PS3_MODULE) |
140 | struct ps3_prealloc ps3fb_videomemory = { | 144 | struct ps3_prealloc ps3fb_videomemory = { |
141 | .name = "ps3fb videomemory", | 145 | .name = "ps3fb videomemory", |
142 | .size = CONFIG_FB_PS3_DEFAULT_SIZE_M*1024*1024, | 146 | .size = CONFIG_FB_PS3_DEFAULT_SIZE_M*1024*1024, |
143 | .align = 1024*1024 /* the GPU requires 1 MiB alignment */ | 147 | .align = 1024*1024 /* the GPU requires 1 MiB alignment */ |
144 | }; | 148 | }; |
145 | EXPORT_SYMBOL_GPL(ps3fb_videomemory); | 149 | EXPORT_SYMBOL_GPL(ps3fb_videomemory); |
146 | #define prealloc_ps3fb_videomemory() prealloc(&ps3fb_videomemory) | 150 | #define prealloc_ps3fb_videomemory() prealloc(&ps3fb_videomemory) |
147 | 151 | ||
148 | static int __init early_parse_ps3fb(char *p) | 152 | static int __init early_parse_ps3fb(char *p) |
149 | { | 153 | { |
150 | if (!p) | 154 | if (!p) |
151 | return 1; | 155 | return 1; |
152 | 156 | ||
153 | ps3fb_videomemory.size = _ALIGN_UP(memparse(p, &p), | 157 | ps3fb_videomemory.size = _ALIGN_UP(memparse(p, &p), |
154 | ps3fb_videomemory.align); | 158 | ps3fb_videomemory.align); |
155 | return 0; | 159 | return 0; |
156 | } | 160 | } |
157 | early_param("ps3fb", early_parse_ps3fb); | 161 | early_param("ps3fb", early_parse_ps3fb); |
158 | #else | 162 | #else |
159 | #define prealloc_ps3fb_videomemory() do { } while (0) | 163 | #define prealloc_ps3fb_videomemory() do { } while (0) |
160 | #endif | 164 | #endif |
161 | 165 | ||
162 | #if defined(CONFIG_PS3_FLASH) || defined(CONFIG_PS3_FLASH_MODULE) | 166 | #if defined(CONFIG_PS3_FLASH) || defined(CONFIG_PS3_FLASH_MODULE) |
163 | struct ps3_prealloc ps3flash_bounce_buffer = { | 167 | struct ps3_prealloc ps3flash_bounce_buffer = { |
164 | .name = "ps3flash bounce buffer", | 168 | .name = "ps3flash bounce buffer", |
165 | .size = 256*1024, | 169 | .size = 256*1024, |
166 | .align = 256*1024 | 170 | .align = 256*1024 |
167 | }; | 171 | }; |
168 | EXPORT_SYMBOL_GPL(ps3flash_bounce_buffer); | 172 | EXPORT_SYMBOL_GPL(ps3flash_bounce_buffer); |
169 | #define prealloc_ps3flash_bounce_buffer() prealloc(&ps3flash_bounce_buffer) | 173 | #define prealloc_ps3flash_bounce_buffer() prealloc(&ps3flash_bounce_buffer) |
170 | 174 | ||
171 | static int __init early_parse_ps3flash(char *p) | 175 | static int __init early_parse_ps3flash(char *p) |
172 | { | 176 | { |
173 | if (!p) | 177 | if (!p) |
174 | return 1; | 178 | return 1; |
175 | 179 | ||
176 | if (!strcmp(p, "off")) | 180 | if (!strcmp(p, "off")) |
177 | ps3flash_bounce_buffer.size = 0; | 181 | ps3flash_bounce_buffer.size = 0; |
178 | 182 | ||
179 | return 0; | 183 | return 0; |
180 | } | 184 | } |
181 | early_param("ps3flash", early_parse_ps3flash); | 185 | early_param("ps3flash", early_parse_ps3flash); |
182 | #else | 186 | #else |
183 | #define prealloc_ps3flash_bounce_buffer() do { } while (0) | 187 | #define prealloc_ps3flash_bounce_buffer() do { } while (0) |
184 | #endif | 188 | #endif |
185 | 189 | ||
186 | static int ps3_set_dabr(u64 dabr) | 190 | static int ps3_set_dabr(u64 dabr) |
187 | { | 191 | { |
188 | enum {DABR_USER = 1, DABR_KERNEL = 2,}; | 192 | enum {DABR_USER = 1, DABR_KERNEL = 2,}; |
189 | 193 | ||
190 | return lv1_set_dabr(dabr, DABR_KERNEL | DABR_USER) ? -1 : 0; | 194 | return lv1_set_dabr(dabr, DABR_KERNEL | DABR_USER) ? -1 : 0; |
191 | } | 195 | } |
192 | 196 | ||
193 | static void __init ps3_setup_arch(void) | 197 | static void __init ps3_setup_arch(void) |
194 | { | 198 | { |
195 | 199 | ||
196 | DBG(" -> %s:%d\n", __func__, __LINE__); | 200 | DBG(" -> %s:%d\n", __func__, __LINE__); |
197 | 201 | ||
198 | lv1_get_version_info(&ps3_firmware_version.raw); | 202 | lv1_get_version_info(&ps3_firmware_version.raw); |
199 | printk(KERN_INFO "PS3 firmware version %u.%u.%u\n", | 203 | printk(KERN_INFO "PS3 firmware version %u.%u.%u\n", |
200 | ps3_firmware_version.major, ps3_firmware_version.minor, | 204 | ps3_firmware_version.major, ps3_firmware_version.minor, |
201 | ps3_firmware_version.rev); | 205 | ps3_firmware_version.rev); |
202 | 206 | ||
203 | ps3_spu_set_platform(); | 207 | ps3_spu_set_platform(); |
204 | 208 | ||
205 | #ifdef CONFIG_SMP | 209 | #ifdef CONFIG_SMP |
206 | smp_init_ps3(); | 210 | smp_init_ps3(); |
207 | #endif | 211 | #endif |
208 | 212 | ||
209 | #ifdef CONFIG_DUMMY_CONSOLE | 213 | #ifdef CONFIG_DUMMY_CONSOLE |
210 | conswitchp = &dummy_con; | 214 | conswitchp = &dummy_con; |
211 | #endif | 215 | #endif |
212 | 216 | ||
213 | prealloc_ps3fb_videomemory(); | 217 | prealloc_ps3fb_videomemory(); |
214 | prealloc_ps3flash_bounce_buffer(); | 218 | prealloc_ps3flash_bounce_buffer(); |
215 | 219 | ||
216 | ppc_md.power_save = ps3_power_save; | 220 | ppc_md.power_save = ps3_power_save; |
217 | ps3_os_area_init(); | 221 | ps3_os_area_init(); |
218 | 222 | ||
219 | DBG(" <- %s:%d\n", __func__, __LINE__); | 223 | DBG(" <- %s:%d\n", __func__, __LINE__); |
220 | } | 224 | } |
221 | 225 | ||
222 | static void __init ps3_progress(char *s, unsigned short hex) | 226 | static void __init ps3_progress(char *s, unsigned short hex) |
223 | { | 227 | { |
224 | printk("*** %04x : %s\n", hex, s ? s : ""); | 228 | printk("*** %04x : %s\n", hex, s ? s : ""); |
225 | } | 229 | } |
226 | 230 | ||
227 | static int __init ps3_probe(void) | 231 | static int __init ps3_probe(void) |
228 | { | 232 | { |
229 | unsigned long htab_size; | 233 | unsigned long htab_size; |
230 | unsigned long dt_root; | 234 | unsigned long dt_root; |
231 | 235 | ||
232 | DBG(" -> %s:%d\n", __func__, __LINE__); | 236 | DBG(" -> %s:%d\n", __func__, __LINE__); |
233 | 237 | ||
234 | dt_root = of_get_flat_dt_root(); | 238 | dt_root = of_get_flat_dt_root(); |
235 | if (!of_flat_dt_is_compatible(dt_root, "sony,ps3")) | 239 | if (!of_flat_dt_is_compatible(dt_root, "sony,ps3")) |
236 | return 0; | 240 | return 0; |
237 | 241 | ||
238 | powerpc_firmware_features |= FW_FEATURE_PS3_POSSIBLE; | 242 | powerpc_firmware_features |= FW_FEATURE_PS3_POSSIBLE; |
239 | 243 | ||
240 | ps3_os_area_save_params(); | 244 | ps3_os_area_save_params(); |
241 | ps3_mm_init(); | 245 | ps3_mm_init(); |
242 | ps3_mm_vas_create(&htab_size); | 246 | ps3_mm_vas_create(&htab_size); |
243 | ps3_hpte_init(htab_size); | 247 | ps3_hpte_init(htab_size); |
244 | 248 | ||
245 | DBG(" <- %s:%d\n", __func__, __LINE__); | 249 | DBG(" <- %s:%d\n", __func__, __LINE__); |
246 | return 1; | 250 | return 1; |
247 | } | 251 | } |
248 | 252 | ||
249 | #if defined(CONFIG_KEXEC) | 253 | #if defined(CONFIG_KEXEC) |
250 | static void ps3_kexec_cpu_down(int crash_shutdown, int secondary) | 254 | static void ps3_kexec_cpu_down(int crash_shutdown, int secondary) |
251 | { | 255 | { |
252 | int cpu = smp_processor_id(); | 256 | int cpu = smp_processor_id(); |
253 | 257 | ||
254 | DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu); | 258 | DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu); |
255 | 259 | ||
256 | ps3_smp_cleanup_cpu(cpu); | 260 | ps3_smp_cleanup_cpu(cpu); |
257 | ps3_shutdown_IRQ(cpu); | 261 | ps3_shutdown_IRQ(cpu); |
258 | 262 | ||
259 | DBG(" <- %s:%d\n", __func__, __LINE__); | 263 | DBG(" <- %s:%d\n", __func__, __LINE__); |
260 | } | 264 | } |
261 | #endif | 265 | #endif |
262 | 266 | ||
263 | define_machine(ps3) { | 267 | define_machine(ps3) { |
264 | .name = "PS3", | 268 | .name = "PS3", |
265 | .probe = ps3_probe, | 269 | .probe = ps3_probe, |
266 | .setup_arch = ps3_setup_arch, | 270 | .setup_arch = ps3_setup_arch, |
267 | .init_IRQ = ps3_init_IRQ, | 271 | .init_IRQ = ps3_init_IRQ, |
268 | .panic = ps3_panic, | 272 | .panic = ps3_panic, |
269 | .get_boot_time = ps3_get_boot_time, | 273 | .get_boot_time = ps3_get_boot_time, |
270 | .set_rtc_time = ps3_set_rtc_time, | 274 | .set_rtc_time = ps3_set_rtc_time, |
271 | .get_rtc_time = ps3_get_rtc_time, | 275 | .get_rtc_time = ps3_get_rtc_time, |
272 | .set_dabr = ps3_set_dabr, | 276 | .set_dabr = ps3_set_dabr, |
273 | .calibrate_decr = ps3_calibrate_decr, | 277 | .calibrate_decr = ps3_calibrate_decr, |
274 | .progress = ps3_progress, | 278 | .progress = ps3_progress, |
275 | .restart = ps3_restart, | 279 | .restart = ps3_restart, |
276 | .power_off = ps3_power_off, | 280 | .power_off = ps3_power_off, |
277 | .halt = ps3_halt, | 281 | .halt = ps3_halt, |
278 | #if defined(CONFIG_KEXEC) | 282 | #if defined(CONFIG_KEXEC) |
279 | .kexec_cpu_down = ps3_kexec_cpu_down, | 283 | .kexec_cpu_down = ps3_kexec_cpu_down, |
280 | .machine_kexec = default_machine_kexec, | 284 | .machine_kexec = default_machine_kexec, |
281 | .machine_kexec_prepare = default_machine_kexec_prepare, | 285 | .machine_kexec_prepare = default_machine_kexec_prepare, |
282 | .machine_crash_shutdown = default_machine_crash_shutdown, | 286 | .machine_crash_shutdown = default_machine_crash_shutdown, |
283 | #endif | 287 | #endif |
284 | }; | 288 | }; |
285 | 289 |
drivers/ps3/ps3av.c
1 | /* | 1 | /* |
2 | * PS3 AV backend support. | 2 | * PS3 AV backend support. |
3 | * | 3 | * |
4 | * Copyright (C) 2007 Sony Computer Entertainment Inc. | 4 | * Copyright (C) 2007 Sony Computer Entertainment Inc. |
5 | * Copyright 2007 Sony Corp. | 5 | * Copyright 2007 Sony Corp. |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License as published by | 8 | * it under the terms of the GNU General Public License as published by |
9 | * the Free Software Foundation; version 2 of the License. | 9 | * the Free Software Foundation; version 2 of the License. |
10 | * | 10 | * |
11 | * This program is distributed in the hope that it will be useful, | 11 | * This program is distributed in the hope that it will be useful, |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | * GNU General Public License for more details. | 14 | * GNU General Public License for more details. |
15 | * | 15 | * |
16 | * You should have received a copy of the GNU General Public License | 16 | * You should have received a copy of the GNU General Public License |
17 | * along with this program; if not, write to the Free Software | 17 | * along with this program; if not, write to the Free Software |
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
19 | */ | 19 | */ |
20 | 20 | ||
21 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
23 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
24 | #include <linux/notifier.h> | 24 | #include <linux/notifier.h> |
25 | #include <linux/ioctl.h> | 25 | #include <linux/ioctl.h> |
26 | #include <linux/fb.h> | 26 | #include <linux/fb.h> |
27 | 27 | ||
28 | #include <asm/firmware.h> | 28 | #include <asm/firmware.h> |
29 | #include <asm/ps3av.h> | 29 | #include <asm/ps3av.h> |
30 | #include <asm/ps3.h> | 30 | #include <asm/ps3.h> |
31 | 31 | ||
32 | #include "vuart.h" | 32 | #include "vuart.h" |
33 | 33 | ||
34 | #define BUFSIZE 4096 /* vuart buf size */ | 34 | #define BUFSIZE 4096 /* vuart buf size */ |
35 | #define PS3AV_BUF_SIZE 512 /* max packet size */ | 35 | #define PS3AV_BUF_SIZE 512 /* max packet size */ |
36 | 36 | ||
37 | static int safe_mode; | 37 | static int safe_mode; |
38 | 38 | ||
39 | static int timeout = 5000; /* in msec ( 5 sec ) */ | 39 | static int timeout = 5000; /* in msec ( 5 sec ) */ |
40 | module_param(timeout, int, 0644); | 40 | module_param(timeout, int, 0644); |
41 | 41 | ||
42 | static struct ps3av { | 42 | static struct ps3av { |
43 | struct mutex mutex; | 43 | struct mutex mutex; |
44 | struct work_struct work; | 44 | struct work_struct work; |
45 | struct completion done; | 45 | struct completion done; |
46 | struct workqueue_struct *wq; | 46 | struct workqueue_struct *wq; |
47 | int open_count; | 47 | int open_count; |
48 | struct ps3_system_bus_device *dev; | 48 | struct ps3_system_bus_device *dev; |
49 | 49 | ||
50 | int region; | 50 | int region; |
51 | struct ps3av_pkt_av_get_hw_conf av_hw_conf; | 51 | struct ps3av_pkt_av_get_hw_conf av_hw_conf; |
52 | u32 av_port[PS3AV_AV_PORT_MAX + PS3AV_OPT_PORT_MAX]; | 52 | u32 av_port[PS3AV_AV_PORT_MAX + PS3AV_OPT_PORT_MAX]; |
53 | u32 opt_port[PS3AV_OPT_PORT_MAX]; | 53 | u32 opt_port[PS3AV_OPT_PORT_MAX]; |
54 | u32 head[PS3AV_HEAD_MAX]; | 54 | u32 head[PS3AV_HEAD_MAX]; |
55 | u32 audio_port; | 55 | u32 audio_port; |
56 | int ps3av_mode; | 56 | int ps3av_mode; |
57 | int ps3av_mode_old; | 57 | int ps3av_mode_old; |
58 | union { | 58 | union { |
59 | struct ps3av_reply_hdr reply_hdr; | 59 | struct ps3av_reply_hdr reply_hdr; |
60 | u8 raw[PS3AV_BUF_SIZE]; | 60 | u8 raw[PS3AV_BUF_SIZE]; |
61 | } recv_buf; | 61 | } recv_buf; |
62 | void (*flip_ctl)(int on, void *data); | ||
63 | void *flip_data; | ||
64 | } *ps3av; | 62 | } *ps3av; |
65 | 63 | ||
66 | /* color space */ | 64 | /* color space */ |
67 | #define YUV444 PS3AV_CMD_VIDEO_CS_YUV444_8 | 65 | #define YUV444 PS3AV_CMD_VIDEO_CS_YUV444_8 |
68 | #define RGB8 PS3AV_CMD_VIDEO_CS_RGB_8 | 66 | #define RGB8 PS3AV_CMD_VIDEO_CS_RGB_8 |
69 | /* format */ | 67 | /* format */ |
70 | #define XRGB PS3AV_CMD_VIDEO_FMT_X8R8G8B8 | 68 | #define XRGB PS3AV_CMD_VIDEO_FMT_X8R8G8B8 |
71 | /* aspect */ | 69 | /* aspect */ |
72 | #define A_N PS3AV_CMD_AV_ASPECT_4_3 | 70 | #define A_N PS3AV_CMD_AV_ASPECT_4_3 |
73 | #define A_W PS3AV_CMD_AV_ASPECT_16_9 | 71 | #define A_W PS3AV_CMD_AV_ASPECT_16_9 |
74 | static const struct avset_video_mode { | 72 | static const struct avset_video_mode { |
75 | u32 cs; | 73 | u32 cs; |
76 | u32 fmt; | 74 | u32 fmt; |
77 | u32 vid; | 75 | u32 vid; |
78 | u32 aspect; | 76 | u32 aspect; |
79 | u32 x; | 77 | u32 x; |
80 | u32 y; | 78 | u32 y; |
81 | } video_mode_table[] = { | 79 | } video_mode_table[] = { |
82 | { 0, }, /* auto */ | 80 | { 0, }, /* auto */ |
83 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_480I, A_N, 720, 480}, | 81 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_480I, A_N, 720, 480}, |
84 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_480P, A_N, 720, 480}, | 82 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_480P, A_N, 720, 480}, |
85 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_720P_60HZ, A_N, 1280, 720}, | 83 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_720P_60HZ, A_N, 1280, 720}, |
86 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080I_60HZ, A_W, 1920, 1080}, | 84 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080I_60HZ, A_W, 1920, 1080}, |
87 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080P_60HZ, A_W, 1920, 1080}, | 85 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080P_60HZ, A_W, 1920, 1080}, |
88 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_576I, A_N, 720, 576}, | 86 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_576I, A_N, 720, 576}, |
89 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_576P, A_N, 720, 576}, | 87 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_576P, A_N, 720, 576}, |
90 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_720P_50HZ, A_N, 1280, 720}, | 88 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_720P_50HZ, A_N, 1280, 720}, |
91 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080I_50HZ, A_W, 1920, 1080}, | 89 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080I_50HZ, A_W, 1920, 1080}, |
92 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080P_50HZ, A_W, 1920, 1080}, | 90 | {YUV444, XRGB, PS3AV_CMD_VIDEO_VID_1080P_50HZ, A_W, 1920, 1080}, |
93 | { RGB8, XRGB, PS3AV_CMD_VIDEO_VID_WXGA, A_W, 1280, 768}, | 91 | { RGB8, XRGB, PS3AV_CMD_VIDEO_VID_WXGA, A_W, 1280, 768}, |
94 | { RGB8, XRGB, PS3AV_CMD_VIDEO_VID_SXGA, A_N, 1280, 1024}, | 92 | { RGB8, XRGB, PS3AV_CMD_VIDEO_VID_SXGA, A_N, 1280, 1024}, |
95 | { RGB8, XRGB, PS3AV_CMD_VIDEO_VID_WUXGA, A_W, 1920, 1200}, | 93 | { RGB8, XRGB, PS3AV_CMD_VIDEO_VID_WUXGA, A_W, 1920, 1200}, |
96 | }; | 94 | }; |
97 | 95 | ||
98 | /* supported CIDs */ | 96 | /* supported CIDs */ |
99 | static u32 cmd_table[] = { | 97 | static u32 cmd_table[] = { |
100 | /* init */ | 98 | /* init */ |
101 | PS3AV_CID_AV_INIT, | 99 | PS3AV_CID_AV_INIT, |
102 | PS3AV_CID_AV_FIN, | 100 | PS3AV_CID_AV_FIN, |
103 | PS3AV_CID_VIDEO_INIT, | 101 | PS3AV_CID_VIDEO_INIT, |
104 | PS3AV_CID_AUDIO_INIT, | 102 | PS3AV_CID_AUDIO_INIT, |
105 | 103 | ||
106 | /* set */ | 104 | /* set */ |
107 | PS3AV_CID_AV_ENABLE_EVENT, | 105 | PS3AV_CID_AV_ENABLE_EVENT, |
108 | PS3AV_CID_AV_DISABLE_EVENT, | 106 | PS3AV_CID_AV_DISABLE_EVENT, |
109 | 107 | ||
110 | PS3AV_CID_AV_VIDEO_CS, | 108 | PS3AV_CID_AV_VIDEO_CS, |
111 | PS3AV_CID_AV_VIDEO_MUTE, | 109 | PS3AV_CID_AV_VIDEO_MUTE, |
112 | PS3AV_CID_AV_VIDEO_DISABLE_SIG, | 110 | PS3AV_CID_AV_VIDEO_DISABLE_SIG, |
113 | PS3AV_CID_AV_AUDIO_PARAM, | 111 | PS3AV_CID_AV_AUDIO_PARAM, |
114 | PS3AV_CID_AV_AUDIO_MUTE, | 112 | PS3AV_CID_AV_AUDIO_MUTE, |
115 | PS3AV_CID_AV_HDMI_MODE, | 113 | PS3AV_CID_AV_HDMI_MODE, |
116 | PS3AV_CID_AV_TV_MUTE, | 114 | PS3AV_CID_AV_TV_MUTE, |
117 | 115 | ||
118 | PS3AV_CID_VIDEO_MODE, | 116 | PS3AV_CID_VIDEO_MODE, |
119 | PS3AV_CID_VIDEO_FORMAT, | 117 | PS3AV_CID_VIDEO_FORMAT, |
120 | PS3AV_CID_VIDEO_PITCH, | 118 | PS3AV_CID_VIDEO_PITCH, |
121 | 119 | ||
122 | PS3AV_CID_AUDIO_MODE, | 120 | PS3AV_CID_AUDIO_MODE, |
123 | PS3AV_CID_AUDIO_MUTE, | 121 | PS3AV_CID_AUDIO_MUTE, |
124 | PS3AV_CID_AUDIO_ACTIVE, | 122 | PS3AV_CID_AUDIO_ACTIVE, |
125 | PS3AV_CID_AUDIO_INACTIVE, | 123 | PS3AV_CID_AUDIO_INACTIVE, |
126 | PS3AV_CID_AVB_PARAM, | 124 | PS3AV_CID_AVB_PARAM, |
127 | 125 | ||
128 | /* get */ | 126 | /* get */ |
129 | PS3AV_CID_AV_GET_HW_CONF, | 127 | PS3AV_CID_AV_GET_HW_CONF, |
130 | PS3AV_CID_AV_GET_MONITOR_INFO, | 128 | PS3AV_CID_AV_GET_MONITOR_INFO, |
131 | 129 | ||
132 | /* event */ | 130 | /* event */ |
133 | PS3AV_CID_EVENT_UNPLUGGED, | 131 | PS3AV_CID_EVENT_UNPLUGGED, |
134 | PS3AV_CID_EVENT_PLUGGED, | 132 | PS3AV_CID_EVENT_PLUGGED, |
135 | PS3AV_CID_EVENT_HDCP_DONE, | 133 | PS3AV_CID_EVENT_HDCP_DONE, |
136 | PS3AV_CID_EVENT_HDCP_FAIL, | 134 | PS3AV_CID_EVENT_HDCP_FAIL, |
137 | PS3AV_CID_EVENT_HDCP_AUTH, | 135 | PS3AV_CID_EVENT_HDCP_AUTH, |
138 | PS3AV_CID_EVENT_HDCP_ERROR, | 136 | PS3AV_CID_EVENT_HDCP_ERROR, |
139 | 137 | ||
140 | 0 | 138 | 0 |
141 | }; | 139 | }; |
142 | 140 | ||
143 | #define PS3AV_EVENT_CMD_MASK 0x10000000 | 141 | #define PS3AV_EVENT_CMD_MASK 0x10000000 |
144 | #define PS3AV_EVENT_ID_MASK 0x0000ffff | 142 | #define PS3AV_EVENT_ID_MASK 0x0000ffff |
145 | #define PS3AV_CID_MASK 0xffffffff | 143 | #define PS3AV_CID_MASK 0xffffffff |
146 | #define PS3AV_REPLY_BIT 0x80000000 | 144 | #define PS3AV_REPLY_BIT 0x80000000 |
147 | 145 | ||
148 | #define ps3av_event_get_port_id(cid) ((cid >> 16) & 0xff) | 146 | #define ps3av_event_get_port_id(cid) ((cid >> 16) & 0xff) |
149 | 147 | ||
150 | static u32 *ps3av_search_cmd_table(u32 cid, u32 mask) | 148 | static u32 *ps3av_search_cmd_table(u32 cid, u32 mask) |
151 | { | 149 | { |
152 | u32 *table; | 150 | u32 *table; |
153 | int i; | 151 | int i; |
154 | 152 | ||
155 | table = cmd_table; | 153 | table = cmd_table; |
156 | for (i = 0;; table++, i++) { | 154 | for (i = 0;; table++, i++) { |
157 | if ((*table & mask) == (cid & mask)) | 155 | if ((*table & mask) == (cid & mask)) |
158 | break; | 156 | break; |
159 | if (*table == 0) | 157 | if (*table == 0) |
160 | return NULL; | 158 | return NULL; |
161 | } | 159 | } |
162 | return table; | 160 | return table; |
163 | } | 161 | } |
164 | 162 | ||
165 | static int ps3av_parse_event_packet(const struct ps3av_reply_hdr *hdr) | 163 | static int ps3av_parse_event_packet(const struct ps3av_reply_hdr *hdr) |
166 | { | 164 | { |
167 | u32 *table; | 165 | u32 *table; |
168 | 166 | ||
169 | if (hdr->cid & PS3AV_EVENT_CMD_MASK) { | 167 | if (hdr->cid & PS3AV_EVENT_CMD_MASK) { |
170 | table = ps3av_search_cmd_table(hdr->cid, PS3AV_EVENT_CMD_MASK); | 168 | table = ps3av_search_cmd_table(hdr->cid, PS3AV_EVENT_CMD_MASK); |
171 | if (table) | 169 | if (table) |
172 | dev_dbg(&ps3av->dev->core, | 170 | dev_dbg(&ps3av->dev->core, |
173 | "recv event packet cid:%08x port:0x%x size:%d\n", | 171 | "recv event packet cid:%08x port:0x%x size:%d\n", |
174 | hdr->cid, ps3av_event_get_port_id(hdr->cid), | 172 | hdr->cid, ps3av_event_get_port_id(hdr->cid), |
175 | hdr->size); | 173 | hdr->size); |
176 | else | 174 | else |
177 | printk(KERN_ERR | 175 | printk(KERN_ERR |
178 | "%s: failed event packet, cid:%08x size:%d\n", | 176 | "%s: failed event packet, cid:%08x size:%d\n", |
179 | __func__, hdr->cid, hdr->size); | 177 | __func__, hdr->cid, hdr->size); |
180 | return 1; /* receive event packet */ | 178 | return 1; /* receive event packet */ |
181 | } | 179 | } |
182 | return 0; | 180 | return 0; |
183 | } | 181 | } |
184 | 182 | ||
185 | 183 | ||
186 | #define POLLING_INTERVAL 25 /* in msec */ | 184 | #define POLLING_INTERVAL 25 /* in msec */ |
187 | 185 | ||
188 | static int ps3av_vuart_write(struct ps3_system_bus_device *dev, | 186 | static int ps3av_vuart_write(struct ps3_system_bus_device *dev, |
189 | const void *buf, unsigned long size) | 187 | const void *buf, unsigned long size) |
190 | { | 188 | { |
191 | int error; | 189 | int error; |
192 | dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__); | 190 | dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__); |
193 | error = ps3_vuart_write(dev, buf, size); | 191 | error = ps3_vuart_write(dev, buf, size); |
194 | dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__); | 192 | dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__); |
195 | return error ? error : size; | 193 | return error ? error : size; |
196 | } | 194 | } |
197 | 195 | ||
198 | static int ps3av_vuart_read(struct ps3_system_bus_device *dev, void *buf, | 196 | static int ps3av_vuart_read(struct ps3_system_bus_device *dev, void *buf, |
199 | unsigned long size, int timeout) | 197 | unsigned long size, int timeout) |
200 | { | 198 | { |
201 | int error; | 199 | int error; |
202 | int loopcnt = 0; | 200 | int loopcnt = 0; |
203 | 201 | ||
204 | dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__); | 202 | dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__); |
205 | timeout = (timeout + POLLING_INTERVAL - 1) / POLLING_INTERVAL; | 203 | timeout = (timeout + POLLING_INTERVAL - 1) / POLLING_INTERVAL; |
206 | while (loopcnt++ <= timeout) { | 204 | while (loopcnt++ <= timeout) { |
207 | error = ps3_vuart_read(dev, buf, size); | 205 | error = ps3_vuart_read(dev, buf, size); |
208 | if (!error) | 206 | if (!error) |
209 | return size; | 207 | return size; |
210 | if (error != -EAGAIN) { | 208 | if (error != -EAGAIN) { |
211 | printk(KERN_ERR "%s: ps3_vuart_read failed %d\n", | 209 | printk(KERN_ERR "%s: ps3_vuart_read failed %d\n", |
212 | __func__, error); | 210 | __func__, error); |
213 | return error; | 211 | return error; |
214 | } | 212 | } |
215 | msleep(POLLING_INTERVAL); | 213 | msleep(POLLING_INTERVAL); |
216 | } | 214 | } |
217 | return -EWOULDBLOCK; | 215 | return -EWOULDBLOCK; |
218 | } | 216 | } |
219 | 217 | ||
220 | static int ps3av_send_cmd_pkt(const struct ps3av_send_hdr *send_buf, | 218 | static int ps3av_send_cmd_pkt(const struct ps3av_send_hdr *send_buf, |
221 | struct ps3av_reply_hdr *recv_buf, int write_len, | 219 | struct ps3av_reply_hdr *recv_buf, int write_len, |
222 | int read_len) | 220 | int read_len) |
223 | { | 221 | { |
224 | int res; | 222 | int res; |
225 | u32 cmd; | 223 | u32 cmd; |
226 | int event; | 224 | int event; |
227 | 225 | ||
228 | if (!ps3av) | 226 | if (!ps3av) |
229 | return -ENODEV; | 227 | return -ENODEV; |
230 | 228 | ||
231 | /* send pkt */ | 229 | /* send pkt */ |
232 | res = ps3av_vuart_write(ps3av->dev, send_buf, write_len); | 230 | res = ps3av_vuart_write(ps3av->dev, send_buf, write_len); |
233 | if (res < 0) { | 231 | if (res < 0) { |
234 | dev_dbg(&ps3av->dev->core, | 232 | dev_dbg(&ps3av->dev->core, |
235 | "%s: ps3av_vuart_write() failed (result=%d)\n", | 233 | "%s: ps3av_vuart_write() failed (result=%d)\n", |
236 | __func__, res); | 234 | __func__, res); |
237 | return res; | 235 | return res; |
238 | } | 236 | } |
239 | 237 | ||
240 | /* recv pkt */ | 238 | /* recv pkt */ |
241 | cmd = send_buf->cid; | 239 | cmd = send_buf->cid; |
242 | do { | 240 | do { |
243 | /* read header */ | 241 | /* read header */ |
244 | res = ps3av_vuart_read(ps3av->dev, recv_buf, PS3AV_HDR_SIZE, | 242 | res = ps3av_vuart_read(ps3av->dev, recv_buf, PS3AV_HDR_SIZE, |
245 | timeout); | 243 | timeout); |
246 | if (res != PS3AV_HDR_SIZE) { | 244 | if (res != PS3AV_HDR_SIZE) { |
247 | dev_dbg(&ps3av->dev->core, | 245 | dev_dbg(&ps3av->dev->core, |
248 | "%s: ps3av_vuart_read() failed (result=%d)\n", | 246 | "%s: ps3av_vuart_read() failed (result=%d)\n", |
249 | __func__, res); | 247 | __func__, res); |
250 | return res; | 248 | return res; |
251 | } | 249 | } |
252 | 250 | ||
253 | /* read body */ | 251 | /* read body */ |
254 | res = ps3av_vuart_read(ps3av->dev, &recv_buf->cid, | 252 | res = ps3av_vuart_read(ps3av->dev, &recv_buf->cid, |
255 | recv_buf->size, timeout); | 253 | recv_buf->size, timeout); |
256 | if (res < 0) { | 254 | if (res < 0) { |
257 | dev_dbg(&ps3av->dev->core, | 255 | dev_dbg(&ps3av->dev->core, |
258 | "%s: ps3av_vuart_read() failed (result=%d)\n", | 256 | "%s: ps3av_vuart_read() failed (result=%d)\n", |
259 | __func__, res); | 257 | __func__, res); |
260 | return res; | 258 | return res; |
261 | } | 259 | } |
262 | res += PS3AV_HDR_SIZE; /* total len */ | 260 | res += PS3AV_HDR_SIZE; /* total len */ |
263 | event = ps3av_parse_event_packet(recv_buf); | 261 | event = ps3av_parse_event_packet(recv_buf); |
264 | /* ret > 0 event packet */ | 262 | /* ret > 0 event packet */ |
265 | } while (event); | 263 | } while (event); |
266 | 264 | ||
267 | if ((cmd | PS3AV_REPLY_BIT) != recv_buf->cid) { | 265 | if ((cmd | PS3AV_REPLY_BIT) != recv_buf->cid) { |
268 | dev_dbg(&ps3av->dev->core, "%s: reply err (result=%x)\n", | 266 | dev_dbg(&ps3av->dev->core, "%s: reply err (result=%x)\n", |
269 | __func__, recv_buf->cid); | 267 | __func__, recv_buf->cid); |
270 | return -EINVAL; | 268 | return -EINVAL; |
271 | } | 269 | } |
272 | 270 | ||
273 | return 0; | 271 | return 0; |
274 | } | 272 | } |
275 | 273 | ||
276 | static int ps3av_process_reply_packet(struct ps3av_send_hdr *cmd_buf, | 274 | static int ps3av_process_reply_packet(struct ps3av_send_hdr *cmd_buf, |
277 | const struct ps3av_reply_hdr *recv_buf, | 275 | const struct ps3av_reply_hdr *recv_buf, |
278 | int user_buf_size) | 276 | int user_buf_size) |
279 | { | 277 | { |
280 | int return_len; | 278 | int return_len; |
281 | 279 | ||
282 | if (recv_buf->version != PS3AV_VERSION) { | 280 | if (recv_buf->version != PS3AV_VERSION) { |
283 | dev_dbg(&ps3av->dev->core, "reply_packet invalid version:%x\n", | 281 | dev_dbg(&ps3av->dev->core, "reply_packet invalid version:%x\n", |
284 | recv_buf->version); | 282 | recv_buf->version); |
285 | return -EFAULT; | 283 | return -EFAULT; |
286 | } | 284 | } |
287 | return_len = recv_buf->size + PS3AV_HDR_SIZE; | 285 | return_len = recv_buf->size + PS3AV_HDR_SIZE; |
288 | if (return_len > user_buf_size) | 286 | if (return_len > user_buf_size) |
289 | return_len = user_buf_size; | 287 | return_len = user_buf_size; |
290 | memcpy(cmd_buf, recv_buf, return_len); | 288 | memcpy(cmd_buf, recv_buf, return_len); |
291 | return 0; /* success */ | 289 | return 0; /* success */ |
292 | } | 290 | } |
293 | 291 | ||
294 | void ps3av_set_hdr(u32 cid, u16 size, struct ps3av_send_hdr *hdr) | 292 | void ps3av_set_hdr(u32 cid, u16 size, struct ps3av_send_hdr *hdr) |
295 | { | 293 | { |
296 | hdr->version = PS3AV_VERSION; | 294 | hdr->version = PS3AV_VERSION; |
297 | hdr->size = size - PS3AV_HDR_SIZE; | 295 | hdr->size = size - PS3AV_HDR_SIZE; |
298 | hdr->cid = cid; | 296 | hdr->cid = cid; |
299 | } | 297 | } |
300 | 298 | ||
301 | int ps3av_do_pkt(u32 cid, u16 send_len, size_t usr_buf_size, | 299 | int ps3av_do_pkt(u32 cid, u16 send_len, size_t usr_buf_size, |
302 | struct ps3av_send_hdr *buf) | 300 | struct ps3av_send_hdr *buf) |
303 | { | 301 | { |
304 | int res = 0; | 302 | int res = 0; |
305 | u32 *table; | 303 | u32 *table; |
306 | 304 | ||
307 | BUG_ON(!ps3av); | 305 | BUG_ON(!ps3av); |
308 | 306 | ||
309 | mutex_lock(&ps3av->mutex); | 307 | mutex_lock(&ps3av->mutex); |
310 | 308 | ||
311 | table = ps3av_search_cmd_table(cid, PS3AV_CID_MASK); | 309 | table = ps3av_search_cmd_table(cid, PS3AV_CID_MASK); |
312 | BUG_ON(!table); | 310 | BUG_ON(!table); |
313 | BUG_ON(send_len < PS3AV_HDR_SIZE); | 311 | BUG_ON(send_len < PS3AV_HDR_SIZE); |
314 | BUG_ON(usr_buf_size < send_len); | 312 | BUG_ON(usr_buf_size < send_len); |
315 | BUG_ON(usr_buf_size > PS3AV_BUF_SIZE); | 313 | BUG_ON(usr_buf_size > PS3AV_BUF_SIZE); |
316 | 314 | ||
317 | /* create header */ | 315 | /* create header */ |
318 | ps3av_set_hdr(cid, send_len, buf); | 316 | ps3av_set_hdr(cid, send_len, buf); |
319 | 317 | ||
320 | /* send packet via vuart */ | 318 | /* send packet via vuart */ |
321 | res = ps3av_send_cmd_pkt(buf, &ps3av->recv_buf.reply_hdr, send_len, | 319 | res = ps3av_send_cmd_pkt(buf, &ps3av->recv_buf.reply_hdr, send_len, |
322 | usr_buf_size); | 320 | usr_buf_size); |
323 | if (res < 0) { | 321 | if (res < 0) { |
324 | printk(KERN_ERR | 322 | printk(KERN_ERR |
325 | "%s: ps3av_send_cmd_pkt() failed (result=%d)\n", | 323 | "%s: ps3av_send_cmd_pkt() failed (result=%d)\n", |
326 | __func__, res); | 324 | __func__, res); |
327 | goto err; | 325 | goto err; |
328 | } | 326 | } |
329 | 327 | ||
330 | /* process reply packet */ | 328 | /* process reply packet */ |
331 | res = ps3av_process_reply_packet(buf, &ps3av->recv_buf.reply_hdr, | 329 | res = ps3av_process_reply_packet(buf, &ps3av->recv_buf.reply_hdr, |
332 | usr_buf_size); | 330 | usr_buf_size); |
333 | if (res < 0) { | 331 | if (res < 0) { |
334 | printk(KERN_ERR "%s: put_return_status() failed (result=%d)\n", | 332 | printk(KERN_ERR "%s: put_return_status() failed (result=%d)\n", |
335 | __func__, res); | 333 | __func__, res); |
336 | goto err; | 334 | goto err; |
337 | } | 335 | } |
338 | 336 | ||
339 | mutex_unlock(&ps3av->mutex); | 337 | mutex_unlock(&ps3av->mutex); |
340 | return 0; | 338 | return 0; |
341 | 339 | ||
342 | err: | 340 | err: |
343 | mutex_unlock(&ps3av->mutex); | 341 | mutex_unlock(&ps3av->mutex); |
344 | printk(KERN_ERR "%s: failed cid:%x res:%d\n", __func__, cid, res); | 342 | printk(KERN_ERR "%s: failed cid:%x res:%d\n", __func__, cid, res); |
345 | return res; | 343 | return res; |
346 | } | 344 | } |
347 | 345 | ||
348 | static int ps3av_set_av_video_mute(u32 mute) | 346 | static int ps3av_set_av_video_mute(u32 mute) |
349 | { | 347 | { |
350 | int i, num_of_av_port, res; | 348 | int i, num_of_av_port, res; |
351 | 349 | ||
352 | num_of_av_port = ps3av->av_hw_conf.num_of_hdmi + | 350 | num_of_av_port = ps3av->av_hw_conf.num_of_hdmi + |
353 | ps3av->av_hw_conf.num_of_avmulti; | 351 | ps3av->av_hw_conf.num_of_avmulti; |
354 | /* video mute on */ | 352 | /* video mute on */ |
355 | for (i = 0; i < num_of_av_port; i++) { | 353 | for (i = 0; i < num_of_av_port; i++) { |
356 | res = ps3av_cmd_av_video_mute(1, &ps3av->av_port[i], mute); | 354 | res = ps3av_cmd_av_video_mute(1, &ps3av->av_port[i], mute); |
357 | if (res < 0) | 355 | if (res < 0) |
358 | return -1; | 356 | return -1; |
359 | } | 357 | } |
360 | 358 | ||
361 | return 0; | 359 | return 0; |
362 | } | 360 | } |
363 | 361 | ||
364 | static int ps3av_set_video_disable_sig(void) | 362 | static int ps3av_set_video_disable_sig(void) |
365 | { | 363 | { |
366 | int i, num_of_hdmi_port, num_of_av_port, res; | 364 | int i, num_of_hdmi_port, num_of_av_port, res; |
367 | 365 | ||
368 | num_of_hdmi_port = ps3av->av_hw_conf.num_of_hdmi; | 366 | num_of_hdmi_port = ps3av->av_hw_conf.num_of_hdmi; |
369 | num_of_av_port = ps3av->av_hw_conf.num_of_hdmi + | 367 | num_of_av_port = ps3av->av_hw_conf.num_of_hdmi + |
370 | ps3av->av_hw_conf.num_of_avmulti; | 368 | ps3av->av_hw_conf.num_of_avmulti; |
371 | 369 | ||
372 | /* tv mute */ | 370 | /* tv mute */ |
373 | for (i = 0; i < num_of_hdmi_port; i++) { | 371 | for (i = 0; i < num_of_hdmi_port; i++) { |
374 | res = ps3av_cmd_av_tv_mute(ps3av->av_port[i], | 372 | res = ps3av_cmd_av_tv_mute(ps3av->av_port[i], |
375 | PS3AV_CMD_MUTE_ON); | 373 | PS3AV_CMD_MUTE_ON); |
376 | if (res < 0) | 374 | if (res < 0) |
377 | return -1; | 375 | return -1; |
378 | } | 376 | } |
379 | msleep(100); | 377 | msleep(100); |
380 | 378 | ||
381 | /* video mute on */ | 379 | /* video mute on */ |
382 | for (i = 0; i < num_of_av_port; i++) { | 380 | for (i = 0; i < num_of_av_port; i++) { |
383 | res = ps3av_cmd_av_video_disable_sig(ps3av->av_port[i]); | 381 | res = ps3av_cmd_av_video_disable_sig(ps3av->av_port[i]); |
384 | if (res < 0) | 382 | if (res < 0) |
385 | return -1; | 383 | return -1; |
386 | if (i < num_of_hdmi_port) { | 384 | if (i < num_of_hdmi_port) { |
387 | res = ps3av_cmd_av_tv_mute(ps3av->av_port[i], | 385 | res = ps3av_cmd_av_tv_mute(ps3av->av_port[i], |
388 | PS3AV_CMD_MUTE_OFF); | 386 | PS3AV_CMD_MUTE_OFF); |
389 | if (res < 0) | 387 | if (res < 0) |
390 | return -1; | 388 | return -1; |
391 | } | 389 | } |
392 | } | 390 | } |
393 | msleep(300); | 391 | msleep(300); |
394 | 392 | ||
395 | return 0; | 393 | return 0; |
396 | } | 394 | } |
397 | 395 | ||
398 | static int ps3av_set_audio_mute(u32 mute) | 396 | static int ps3av_set_audio_mute(u32 mute) |
399 | { | 397 | { |
400 | int i, num_of_av_port, num_of_opt_port, res; | 398 | int i, num_of_av_port, num_of_opt_port, res; |
401 | 399 | ||
402 | num_of_av_port = ps3av->av_hw_conf.num_of_hdmi + | 400 | num_of_av_port = ps3av->av_hw_conf.num_of_hdmi + |
403 | ps3av->av_hw_conf.num_of_avmulti; | 401 | ps3av->av_hw_conf.num_of_avmulti; |
404 | num_of_opt_port = ps3av->av_hw_conf.num_of_spdif; | 402 | num_of_opt_port = ps3av->av_hw_conf.num_of_spdif; |
405 | 403 | ||
406 | for (i = 0; i < num_of_av_port; i++) { | 404 | for (i = 0; i < num_of_av_port; i++) { |
407 | res = ps3av_cmd_av_audio_mute(1, &ps3av->av_port[i], mute); | 405 | res = ps3av_cmd_av_audio_mute(1, &ps3av->av_port[i], mute); |
408 | if (res < 0) | 406 | if (res < 0) |
409 | return -1; | 407 | return -1; |
410 | } | 408 | } |
411 | for (i = 0; i < num_of_opt_port; i++) { | 409 | for (i = 0; i < num_of_opt_port; i++) { |
412 | res = ps3av_cmd_audio_mute(1, &ps3av->opt_port[i], mute); | 410 | res = ps3av_cmd_audio_mute(1, &ps3av->opt_port[i], mute); |
413 | if (res < 0) | 411 | if (res < 0) |
414 | return -1; | 412 | return -1; |
415 | } | 413 | } |
416 | 414 | ||
417 | return 0; | 415 | return 0; |
418 | } | 416 | } |
419 | 417 | ||
420 | int ps3av_set_audio_mode(u32 ch, u32 fs, u32 word_bits, u32 format, u32 source) | 418 | int ps3av_set_audio_mode(u32 ch, u32 fs, u32 word_bits, u32 format, u32 source) |
421 | { | 419 | { |
422 | struct ps3av_pkt_avb_param avb_param; | 420 | struct ps3av_pkt_avb_param avb_param; |
423 | int i, num_of_audio, vid, res; | 421 | int i, num_of_audio, vid, res; |
424 | struct ps3av_pkt_audio_mode audio_mode; | 422 | struct ps3av_pkt_audio_mode audio_mode; |
425 | u32 len = 0; | 423 | u32 len = 0; |
426 | 424 | ||
427 | num_of_audio = ps3av->av_hw_conf.num_of_hdmi + | 425 | num_of_audio = ps3av->av_hw_conf.num_of_hdmi + |
428 | ps3av->av_hw_conf.num_of_avmulti + | 426 | ps3av->av_hw_conf.num_of_avmulti + |
429 | ps3av->av_hw_conf.num_of_spdif; | 427 | ps3av->av_hw_conf.num_of_spdif; |
430 | 428 | ||
431 | avb_param.num_of_video_pkt = 0; | 429 | avb_param.num_of_video_pkt = 0; |
432 | avb_param.num_of_audio_pkt = PS3AV_AVB_NUM_AUDIO; /* always 0 */ | 430 | avb_param.num_of_audio_pkt = PS3AV_AVB_NUM_AUDIO; /* always 0 */ |
433 | avb_param.num_of_av_video_pkt = 0; | 431 | avb_param.num_of_av_video_pkt = 0; |
434 | avb_param.num_of_av_audio_pkt = ps3av->av_hw_conf.num_of_hdmi; | 432 | avb_param.num_of_av_audio_pkt = ps3av->av_hw_conf.num_of_hdmi; |
435 | 433 | ||
436 | vid = video_mode_table[ps3av->ps3av_mode].vid; | 434 | vid = video_mode_table[ps3av->ps3av_mode].vid; |
437 | 435 | ||
438 | /* audio mute */ | 436 | /* audio mute */ |
439 | ps3av_set_audio_mute(PS3AV_CMD_MUTE_ON); | 437 | ps3av_set_audio_mute(PS3AV_CMD_MUTE_ON); |
440 | 438 | ||
441 | /* audio inactive */ | 439 | /* audio inactive */ |
442 | res = ps3av_cmd_audio_active(0, ps3av->audio_port); | 440 | res = ps3av_cmd_audio_active(0, ps3av->audio_port); |
443 | if (res < 0) | 441 | if (res < 0) |
444 | dev_dbg(&ps3av->dev->core, | 442 | dev_dbg(&ps3av->dev->core, |
445 | "ps3av_cmd_audio_active OFF failed\n"); | 443 | "ps3av_cmd_audio_active OFF failed\n"); |
446 | 444 | ||
447 | /* audio_pkt */ | 445 | /* audio_pkt */ |
448 | for (i = 0; i < num_of_audio; i++) { | 446 | for (i = 0; i < num_of_audio; i++) { |
449 | ps3av_cmd_set_audio_mode(&audio_mode, ps3av->av_port[i], ch, | 447 | ps3av_cmd_set_audio_mode(&audio_mode, ps3av->av_port[i], ch, |
450 | fs, word_bits, format, source); | 448 | fs, word_bits, format, source); |
451 | if (i < ps3av->av_hw_conf.num_of_hdmi) { | 449 | if (i < ps3av->av_hw_conf.num_of_hdmi) { |
452 | /* hdmi only */ | 450 | /* hdmi only */ |
453 | len += ps3av_cmd_set_av_audio_param(&avb_param.buf[len], | 451 | len += ps3av_cmd_set_av_audio_param(&avb_param.buf[len], |
454 | ps3av->av_port[i], | 452 | ps3av->av_port[i], |
455 | &audio_mode, vid); | 453 | &audio_mode, vid); |
456 | } | 454 | } |
457 | /* audio_mode pkt should be sent separately */ | 455 | /* audio_mode pkt should be sent separately */ |
458 | res = ps3av_cmd_audio_mode(&audio_mode); | 456 | res = ps3av_cmd_audio_mode(&audio_mode); |
459 | if (res < 0) | 457 | if (res < 0) |
460 | dev_dbg(&ps3av->dev->core, | 458 | dev_dbg(&ps3av->dev->core, |
461 | "ps3av_cmd_audio_mode failed, port:%x\n", i); | 459 | "ps3av_cmd_audio_mode failed, port:%x\n", i); |
462 | } | 460 | } |
463 | 461 | ||
464 | /* send command using avb pkt */ | 462 | /* send command using avb pkt */ |
465 | len += offsetof(struct ps3av_pkt_avb_param, buf); | 463 | len += offsetof(struct ps3av_pkt_avb_param, buf); |
466 | res = ps3av_cmd_avb_param(&avb_param, len); | 464 | res = ps3av_cmd_avb_param(&avb_param, len); |
467 | if (res < 0) | 465 | if (res < 0) |
468 | dev_dbg(&ps3av->dev->core, "ps3av_cmd_avb_param failed\n"); | 466 | dev_dbg(&ps3av->dev->core, "ps3av_cmd_avb_param failed\n"); |
469 | 467 | ||
470 | /* audio mute */ | 468 | /* audio mute */ |
471 | ps3av_set_audio_mute(PS3AV_CMD_MUTE_OFF); | 469 | ps3av_set_audio_mute(PS3AV_CMD_MUTE_OFF); |
472 | 470 | ||
473 | /* audio active */ | 471 | /* audio active */ |
474 | res = ps3av_cmd_audio_active(1, ps3av->audio_port); | 472 | res = ps3av_cmd_audio_active(1, ps3av->audio_port); |
475 | if (res < 0) | 473 | if (res < 0) |
476 | dev_dbg(&ps3av->dev->core, | 474 | dev_dbg(&ps3av->dev->core, |
477 | "ps3av_cmd_audio_active ON failed\n"); | 475 | "ps3av_cmd_audio_active ON failed\n"); |
478 | 476 | ||
479 | return 0; | 477 | return 0; |
480 | } | 478 | } |
481 | 479 | ||
482 | EXPORT_SYMBOL_GPL(ps3av_set_audio_mode); | 480 | EXPORT_SYMBOL_GPL(ps3av_set_audio_mode); |
483 | 481 | ||
484 | static int ps3av_set_videomode(void) | 482 | static int ps3av_set_videomode(void) |
485 | { | 483 | { |
486 | /* av video mute */ | 484 | /* av video mute */ |
487 | ps3av_set_av_video_mute(PS3AV_CMD_MUTE_ON); | 485 | ps3av_set_av_video_mute(PS3AV_CMD_MUTE_ON); |
488 | 486 | ||
489 | /* wake up ps3avd to do the actual video mode setting */ | 487 | /* wake up ps3avd to do the actual video mode setting */ |
490 | queue_work(ps3av->wq, &ps3av->work); | 488 | queue_work(ps3av->wq, &ps3av->work); |
491 | 489 | ||
492 | return 0; | 490 | return 0; |
493 | } | 491 | } |
494 | 492 | ||
495 | static void ps3av_set_videomode_packet(u32 id) | 493 | static void ps3av_set_videomode_packet(u32 id) |
496 | { | 494 | { |
497 | struct ps3av_pkt_avb_param avb_param; | 495 | struct ps3av_pkt_avb_param avb_param; |
498 | unsigned int i; | 496 | unsigned int i; |
499 | u32 len = 0, av_video_cs; | 497 | u32 len = 0, av_video_cs; |
500 | const struct avset_video_mode *video_mode; | 498 | const struct avset_video_mode *video_mode; |
501 | int res; | 499 | int res; |
502 | 500 | ||
503 | video_mode = &video_mode_table[id & PS3AV_MODE_MASK]; | 501 | video_mode = &video_mode_table[id & PS3AV_MODE_MASK]; |
504 | 502 | ||
505 | avb_param.num_of_video_pkt = PS3AV_AVB_NUM_VIDEO; /* num of head */ | 503 | avb_param.num_of_video_pkt = PS3AV_AVB_NUM_VIDEO; /* num of head */ |
506 | avb_param.num_of_audio_pkt = 0; | 504 | avb_param.num_of_audio_pkt = 0; |
507 | avb_param.num_of_av_video_pkt = ps3av->av_hw_conf.num_of_hdmi + | 505 | avb_param.num_of_av_video_pkt = ps3av->av_hw_conf.num_of_hdmi + |
508 | ps3av->av_hw_conf.num_of_avmulti; | 506 | ps3av->av_hw_conf.num_of_avmulti; |
509 | avb_param.num_of_av_audio_pkt = 0; | 507 | avb_param.num_of_av_audio_pkt = 0; |
510 | 508 | ||
511 | /* video_pkt */ | 509 | /* video_pkt */ |
512 | for (i = 0; i < avb_param.num_of_video_pkt; i++) | 510 | for (i = 0; i < avb_param.num_of_video_pkt; i++) |
513 | len += ps3av_cmd_set_video_mode(&avb_param.buf[len], | 511 | len += ps3av_cmd_set_video_mode(&avb_param.buf[len], |
514 | ps3av->head[i], video_mode->vid, | 512 | ps3av->head[i], video_mode->vid, |
515 | video_mode->fmt, id); | 513 | video_mode->fmt, id); |
516 | /* av_video_pkt */ | 514 | /* av_video_pkt */ |
517 | for (i = 0; i < avb_param.num_of_av_video_pkt; i++) { | 515 | for (i = 0; i < avb_param.num_of_av_video_pkt; i++) { |
518 | if (id & PS3AV_MODE_DVI || id & PS3AV_MODE_RGB) | 516 | if (id & PS3AV_MODE_DVI || id & PS3AV_MODE_RGB) |
519 | av_video_cs = RGB8; | 517 | av_video_cs = RGB8; |
520 | else | 518 | else |
521 | av_video_cs = video_mode->cs; | 519 | av_video_cs = video_mode->cs; |
522 | #ifndef PS3AV_HDMI_YUV | 520 | #ifndef PS3AV_HDMI_YUV |
523 | if (ps3av->av_port[i] == PS3AV_CMD_AVPORT_HDMI_0 || | 521 | if (ps3av->av_port[i] == PS3AV_CMD_AVPORT_HDMI_0 || |
524 | ps3av->av_port[i] == PS3AV_CMD_AVPORT_HDMI_1) | 522 | ps3av->av_port[i] == PS3AV_CMD_AVPORT_HDMI_1) |
525 | av_video_cs = RGB8; /* use RGB for HDMI */ | 523 | av_video_cs = RGB8; /* use RGB for HDMI */ |
526 | #endif | 524 | #endif |
527 | len += ps3av_cmd_set_av_video_cs(&avb_param.buf[len], | 525 | len += ps3av_cmd_set_av_video_cs(&avb_param.buf[len], |
528 | ps3av->av_port[i], | 526 | ps3av->av_port[i], |
529 | video_mode->vid, av_video_cs, | 527 | video_mode->vid, av_video_cs, |
530 | video_mode->aspect, id); | 528 | video_mode->aspect, id); |
531 | } | 529 | } |
532 | /* send command using avb pkt */ | 530 | /* send command using avb pkt */ |
533 | len += offsetof(struct ps3av_pkt_avb_param, buf); | 531 | len += offsetof(struct ps3av_pkt_avb_param, buf); |
534 | res = ps3av_cmd_avb_param(&avb_param, len); | 532 | res = ps3av_cmd_avb_param(&avb_param, len); |
535 | if (res == PS3AV_STATUS_NO_SYNC_HEAD) | 533 | if (res == PS3AV_STATUS_NO_SYNC_HEAD) |
536 | printk(KERN_WARNING | 534 | printk(KERN_WARNING |
537 | "%s: Command failed. Please try your request again. \n", | 535 | "%s: Command failed. Please try your request again. \n", |
538 | __func__); | 536 | __func__); |
539 | else if (res) | 537 | else if (res) |
540 | dev_dbg(&ps3av->dev->core, "ps3av_cmd_avb_param failed\n"); | 538 | dev_dbg(&ps3av->dev->core, "ps3av_cmd_avb_param failed\n"); |
541 | } | 539 | } |
542 | 540 | ||
543 | static void ps3av_set_videomode_cont(u32 id, u32 old_id) | 541 | static void ps3av_set_videomode_cont(u32 id, u32 old_id) |
544 | { | 542 | { |
545 | static int vesa; | 543 | static int vesa; |
546 | int res; | 544 | int res; |
547 | 545 | ||
548 | /* video signal off */ | 546 | /* video signal off */ |
549 | ps3av_set_video_disable_sig(); | 547 | ps3av_set_video_disable_sig(); |
550 | 548 | ||
551 | /* | 549 | /* |
552 | * AV backend needs non-VESA mode setting at least one time | 550 | * AV backend needs non-VESA mode setting at least one time |
553 | * when VESA mode is used. | 551 | * when VESA mode is used. |
554 | */ | 552 | */ |
555 | if (vesa == 0 && (id & PS3AV_MODE_MASK) >= PS3AV_MODE_WXGA) { | 553 | if (vesa == 0 && (id & PS3AV_MODE_MASK) >= PS3AV_MODE_WXGA) { |
556 | /* vesa mode */ | 554 | /* vesa mode */ |
557 | ps3av_set_videomode_packet(PS3AV_MODE_480P); | 555 | ps3av_set_videomode_packet(PS3AV_MODE_480P); |
558 | } | 556 | } |
559 | vesa = 1; | 557 | vesa = 1; |
560 | 558 | ||
561 | /* Retail PS3 product doesn't support this */ | 559 | /* Retail PS3 product doesn't support this */ |
562 | if (id & PS3AV_MODE_HDCP_OFF) { | 560 | if (id & PS3AV_MODE_HDCP_OFF) { |
563 | res = ps3av_cmd_av_hdmi_mode(PS3AV_CMD_AV_HDMI_HDCP_OFF); | 561 | res = ps3av_cmd_av_hdmi_mode(PS3AV_CMD_AV_HDMI_HDCP_OFF); |
564 | if (res == PS3AV_STATUS_UNSUPPORTED_HDMI_MODE) | 562 | if (res == PS3AV_STATUS_UNSUPPORTED_HDMI_MODE) |
565 | dev_dbg(&ps3av->dev->core, "Not supported\n"); | 563 | dev_dbg(&ps3av->dev->core, "Not supported\n"); |
566 | else if (res) | 564 | else if (res) |
567 | dev_dbg(&ps3av->dev->core, | 565 | dev_dbg(&ps3av->dev->core, |
568 | "ps3av_cmd_av_hdmi_mode failed\n"); | 566 | "ps3av_cmd_av_hdmi_mode failed\n"); |
569 | } else if (old_id & PS3AV_MODE_HDCP_OFF) { | 567 | } else if (old_id & PS3AV_MODE_HDCP_OFF) { |
570 | res = ps3av_cmd_av_hdmi_mode(PS3AV_CMD_AV_HDMI_MODE_NORMAL); | 568 | res = ps3av_cmd_av_hdmi_mode(PS3AV_CMD_AV_HDMI_MODE_NORMAL); |
571 | if (res < 0 && res != PS3AV_STATUS_UNSUPPORTED_HDMI_MODE) | 569 | if (res < 0 && res != PS3AV_STATUS_UNSUPPORTED_HDMI_MODE) |
572 | dev_dbg(&ps3av->dev->core, | 570 | dev_dbg(&ps3av->dev->core, |
573 | "ps3av_cmd_av_hdmi_mode failed\n"); | 571 | "ps3av_cmd_av_hdmi_mode failed\n"); |
574 | } | 572 | } |
575 | 573 | ||
576 | ps3av_set_videomode_packet(id); | 574 | ps3av_set_videomode_packet(id); |
577 | 575 | ||
578 | msleep(1500); | 576 | msleep(1500); |
579 | /* av video mute */ | 577 | /* av video mute */ |
580 | ps3av_set_av_video_mute(PS3AV_CMD_MUTE_OFF); | 578 | ps3av_set_av_video_mute(PS3AV_CMD_MUTE_OFF); |
581 | } | 579 | } |
582 | 580 | ||
583 | static void ps3avd(struct work_struct *work) | 581 | static void ps3avd(struct work_struct *work) |
584 | { | 582 | { |
585 | ps3av_set_videomode_cont(ps3av->ps3av_mode, ps3av->ps3av_mode_old); | 583 | ps3av_set_videomode_cont(ps3av->ps3av_mode, ps3av->ps3av_mode_old); |
586 | complete(&ps3av->done); | 584 | complete(&ps3av->done); |
587 | } | 585 | } |
588 | 586 | ||
589 | #define SHIFT_50 0 | 587 | #define SHIFT_50 0 |
590 | #define SHIFT_60 4 | 588 | #define SHIFT_60 4 |
591 | #define SHIFT_VESA 8 | 589 | #define SHIFT_VESA 8 |
592 | 590 | ||
593 | static const struct { | 591 | static const struct { |
594 | unsigned mask : 19; | 592 | unsigned mask : 19; |
595 | unsigned id : 4; | 593 | unsigned id : 4; |
596 | } ps3av_preferred_modes[] = { | 594 | } ps3av_preferred_modes[] = { |
597 | { PS3AV_RESBIT_WUXGA << SHIFT_VESA, PS3AV_MODE_WUXGA }, | 595 | { PS3AV_RESBIT_WUXGA << SHIFT_VESA, PS3AV_MODE_WUXGA }, |
598 | { PS3AV_RESBIT_1920x1080P << SHIFT_60, PS3AV_MODE_1080P60 }, | 596 | { PS3AV_RESBIT_1920x1080P << SHIFT_60, PS3AV_MODE_1080P60 }, |
599 | { PS3AV_RESBIT_1920x1080P << SHIFT_50, PS3AV_MODE_1080P50 }, | 597 | { PS3AV_RESBIT_1920x1080P << SHIFT_50, PS3AV_MODE_1080P50 }, |
600 | { PS3AV_RESBIT_1920x1080I << SHIFT_60, PS3AV_MODE_1080I60 }, | 598 | { PS3AV_RESBIT_1920x1080I << SHIFT_60, PS3AV_MODE_1080I60 }, |
601 | { PS3AV_RESBIT_1920x1080I << SHIFT_50, PS3AV_MODE_1080I50 }, | 599 | { PS3AV_RESBIT_1920x1080I << SHIFT_50, PS3AV_MODE_1080I50 }, |
602 | { PS3AV_RESBIT_SXGA << SHIFT_VESA, PS3AV_MODE_SXGA }, | 600 | { PS3AV_RESBIT_SXGA << SHIFT_VESA, PS3AV_MODE_SXGA }, |
603 | { PS3AV_RESBIT_WXGA << SHIFT_VESA, PS3AV_MODE_WXGA }, | 601 | { PS3AV_RESBIT_WXGA << SHIFT_VESA, PS3AV_MODE_WXGA }, |
604 | { PS3AV_RESBIT_1280x720P << SHIFT_60, PS3AV_MODE_720P60 }, | 602 | { PS3AV_RESBIT_1280x720P << SHIFT_60, PS3AV_MODE_720P60 }, |
605 | { PS3AV_RESBIT_1280x720P << SHIFT_50, PS3AV_MODE_720P50 }, | 603 | { PS3AV_RESBIT_1280x720P << SHIFT_50, PS3AV_MODE_720P50 }, |
606 | { PS3AV_RESBIT_720x480P << SHIFT_60, PS3AV_MODE_480P }, | 604 | { PS3AV_RESBIT_720x480P << SHIFT_60, PS3AV_MODE_480P }, |
607 | { PS3AV_RESBIT_720x576P << SHIFT_50, PS3AV_MODE_576P }, | 605 | { PS3AV_RESBIT_720x576P << SHIFT_50, PS3AV_MODE_576P }, |
608 | }; | 606 | }; |
609 | 607 | ||
610 | static enum ps3av_mode_num ps3av_resbit2id(u32 res_50, u32 res_60, | 608 | static enum ps3av_mode_num ps3av_resbit2id(u32 res_50, u32 res_60, |
611 | u32 res_vesa) | 609 | u32 res_vesa) |
612 | { | 610 | { |
613 | unsigned int i; | 611 | unsigned int i; |
614 | u32 res_all; | 612 | u32 res_all; |
615 | 613 | ||
616 | /* | 614 | /* |
617 | * We mask off the resolution bits we care about and combine the | 615 | * We mask off the resolution bits we care about and combine the |
618 | * results in one bitfield, so make sure there's no overlap | 616 | * results in one bitfield, so make sure there's no overlap |
619 | */ | 617 | */ |
620 | BUILD_BUG_ON(PS3AV_RES_MASK_50 << SHIFT_50 & | 618 | BUILD_BUG_ON(PS3AV_RES_MASK_50 << SHIFT_50 & |
621 | PS3AV_RES_MASK_60 << SHIFT_60); | 619 | PS3AV_RES_MASK_60 << SHIFT_60); |
622 | BUILD_BUG_ON(PS3AV_RES_MASK_50 << SHIFT_50 & | 620 | BUILD_BUG_ON(PS3AV_RES_MASK_50 << SHIFT_50 & |
623 | PS3AV_RES_MASK_VESA << SHIFT_VESA); | 621 | PS3AV_RES_MASK_VESA << SHIFT_VESA); |
624 | BUILD_BUG_ON(PS3AV_RES_MASK_60 << SHIFT_60 & | 622 | BUILD_BUG_ON(PS3AV_RES_MASK_60 << SHIFT_60 & |
625 | PS3AV_RES_MASK_VESA << SHIFT_VESA); | 623 | PS3AV_RES_MASK_VESA << SHIFT_VESA); |
626 | res_all = (res_50 & PS3AV_RES_MASK_50) << SHIFT_50 | | 624 | res_all = (res_50 & PS3AV_RES_MASK_50) << SHIFT_50 | |
627 | (res_60 & PS3AV_RES_MASK_60) << SHIFT_60 | | 625 | (res_60 & PS3AV_RES_MASK_60) << SHIFT_60 | |
628 | (res_vesa & PS3AV_RES_MASK_VESA) << SHIFT_VESA; | 626 | (res_vesa & PS3AV_RES_MASK_VESA) << SHIFT_VESA; |
629 | 627 | ||
630 | if (!res_all) | 628 | if (!res_all) |
631 | return 0; | 629 | return 0; |
632 | 630 | ||
633 | for (i = 0; i < ARRAY_SIZE(ps3av_preferred_modes); i++) | 631 | for (i = 0; i < ARRAY_SIZE(ps3av_preferred_modes); i++) |
634 | if (res_all & ps3av_preferred_modes[i].mask) | 632 | if (res_all & ps3av_preferred_modes[i].mask) |
635 | return ps3av_preferred_modes[i].id; | 633 | return ps3av_preferred_modes[i].id; |
636 | 634 | ||
637 | return 0; | 635 | return 0; |
638 | } | 636 | } |
639 | 637 | ||
640 | static enum ps3av_mode_num ps3av_hdmi_get_id(struct ps3av_info_monitor *info) | 638 | static enum ps3av_mode_num ps3av_hdmi_get_id(struct ps3av_info_monitor *info) |
641 | { | 639 | { |
642 | enum ps3av_mode_num id; | 640 | enum ps3av_mode_num id; |
643 | 641 | ||
644 | if (safe_mode) | 642 | if (safe_mode) |
645 | return PS3AV_DEFAULT_HDMI_MODE_ID_REG_60; | 643 | return PS3AV_DEFAULT_HDMI_MODE_ID_REG_60; |
646 | 644 | ||
647 | /* check native resolution */ | 645 | /* check native resolution */ |
648 | id = ps3av_resbit2id(info->res_50.native, info->res_60.native, | 646 | id = ps3av_resbit2id(info->res_50.native, info->res_60.native, |
649 | info->res_vesa.native); | 647 | info->res_vesa.native); |
650 | if (id) { | 648 | if (id) { |
651 | pr_debug("%s: Using native mode %d\n", __func__, id); | 649 | pr_debug("%s: Using native mode %d\n", __func__, id); |
652 | return id; | 650 | return id; |
653 | } | 651 | } |
654 | 652 | ||
655 | /* check supported resolutions */ | 653 | /* check supported resolutions */ |
656 | id = ps3av_resbit2id(info->res_50.res_bits, info->res_60.res_bits, | 654 | id = ps3av_resbit2id(info->res_50.res_bits, info->res_60.res_bits, |
657 | info->res_vesa.res_bits); | 655 | info->res_vesa.res_bits); |
658 | if (id) { | 656 | if (id) { |
659 | pr_debug("%s: Using supported mode %d\n", __func__, id); | 657 | pr_debug("%s: Using supported mode %d\n", __func__, id); |
660 | return id; | 658 | return id; |
661 | } | 659 | } |
662 | 660 | ||
663 | if (ps3av->region & PS3AV_REGION_60) | 661 | if (ps3av->region & PS3AV_REGION_60) |
664 | id = PS3AV_DEFAULT_HDMI_MODE_ID_REG_60; | 662 | id = PS3AV_DEFAULT_HDMI_MODE_ID_REG_60; |
665 | else | 663 | else |
666 | id = PS3AV_DEFAULT_HDMI_MODE_ID_REG_50; | 664 | id = PS3AV_DEFAULT_HDMI_MODE_ID_REG_50; |
667 | pr_debug("%s: Using default mode %d\n", __func__, id); | 665 | pr_debug("%s: Using default mode %d\n", __func__, id); |
668 | return id; | 666 | return id; |
669 | } | 667 | } |
670 | 668 | ||
671 | static void ps3av_monitor_info_dump(const struct ps3av_pkt_av_get_monitor_info *monitor_info) | 669 | static void ps3av_monitor_info_dump(const struct ps3av_pkt_av_get_monitor_info *monitor_info) |
672 | { | 670 | { |
673 | const struct ps3av_info_monitor *info = &monitor_info->info; | 671 | const struct ps3av_info_monitor *info = &monitor_info->info; |
674 | const struct ps3av_info_audio *audio = info->audio; | 672 | const struct ps3av_info_audio *audio = info->audio; |
675 | char id[sizeof(info->monitor_id)*3+1]; | 673 | char id[sizeof(info->monitor_id)*3+1]; |
676 | int i; | 674 | int i; |
677 | 675 | ||
678 | pr_debug("Monitor Info: size %u\n", monitor_info->send_hdr.size); | 676 | pr_debug("Monitor Info: size %u\n", monitor_info->send_hdr.size); |
679 | 677 | ||
680 | pr_debug("avport: %02x\n", info->avport); | 678 | pr_debug("avport: %02x\n", info->avport); |
681 | for (i = 0; i < sizeof(info->monitor_id); i++) | 679 | for (i = 0; i < sizeof(info->monitor_id); i++) |
682 | sprintf(&id[i*3], " %02x", info->monitor_id[i]); | 680 | sprintf(&id[i*3], " %02x", info->monitor_id[i]); |
683 | pr_debug("monitor_id: %s\n", id); | 681 | pr_debug("monitor_id: %s\n", id); |
684 | pr_debug("monitor_type: %02x\n", info->monitor_type); | 682 | pr_debug("monitor_type: %02x\n", info->monitor_type); |
685 | pr_debug("monitor_name: %.*s\n", (int)sizeof(info->monitor_name), | 683 | pr_debug("monitor_name: %.*s\n", (int)sizeof(info->monitor_name), |
686 | info->monitor_name); | 684 | info->monitor_name); |
687 | 685 | ||
688 | /* resolution */ | 686 | /* resolution */ |
689 | pr_debug("resolution_60: bits: %08x native: %08x\n", | 687 | pr_debug("resolution_60: bits: %08x native: %08x\n", |
690 | info->res_60.res_bits, info->res_60.native); | 688 | info->res_60.res_bits, info->res_60.native); |
691 | pr_debug("resolution_50: bits: %08x native: %08x\n", | 689 | pr_debug("resolution_50: bits: %08x native: %08x\n", |
692 | info->res_50.res_bits, info->res_50.native); | 690 | info->res_50.res_bits, info->res_50.native); |
693 | pr_debug("resolution_other: bits: %08x native: %08x\n", | 691 | pr_debug("resolution_other: bits: %08x native: %08x\n", |
694 | info->res_other.res_bits, info->res_other.native); | 692 | info->res_other.res_bits, info->res_other.native); |
695 | pr_debug("resolution_vesa: bits: %08x native: %08x\n", | 693 | pr_debug("resolution_vesa: bits: %08x native: %08x\n", |
696 | info->res_vesa.res_bits, info->res_vesa.native); | 694 | info->res_vesa.res_bits, info->res_vesa.native); |
697 | 695 | ||
698 | /* color space */ | 696 | /* color space */ |
699 | pr_debug("color space rgb: %02x\n", info->cs.rgb); | 697 | pr_debug("color space rgb: %02x\n", info->cs.rgb); |
700 | pr_debug("color space yuv444: %02x\n", info->cs.yuv444); | 698 | pr_debug("color space yuv444: %02x\n", info->cs.yuv444); |
701 | pr_debug("color space yuv422: %02x\n", info->cs.yuv422); | 699 | pr_debug("color space yuv422: %02x\n", info->cs.yuv422); |
702 | 700 | ||
703 | /* color info */ | 701 | /* color info */ |
704 | pr_debug("color info red: X %04x Y %04x\n", info->color.red_x, | 702 | pr_debug("color info red: X %04x Y %04x\n", info->color.red_x, |
705 | info->color.red_y); | 703 | info->color.red_y); |
706 | pr_debug("color info green: X %04x Y %04x\n", info->color.green_x, | 704 | pr_debug("color info green: X %04x Y %04x\n", info->color.green_x, |
707 | info->color.green_y); | 705 | info->color.green_y); |
708 | pr_debug("color info blue: X %04x Y %04x\n", info->color.blue_x, | 706 | pr_debug("color info blue: X %04x Y %04x\n", info->color.blue_x, |
709 | info->color.blue_y); | 707 | info->color.blue_y); |
710 | pr_debug("color info white: X %04x Y %04x\n", info->color.white_x, | 708 | pr_debug("color info white: X %04x Y %04x\n", info->color.white_x, |
711 | info->color.white_y); | 709 | info->color.white_y); |
712 | pr_debug("color info gamma: %08x\n", info->color.gamma); | 710 | pr_debug("color info gamma: %08x\n", info->color.gamma); |
713 | 711 | ||
714 | /* other info */ | 712 | /* other info */ |
715 | pr_debug("supported_AI: %02x\n", info->supported_ai); | 713 | pr_debug("supported_AI: %02x\n", info->supported_ai); |
716 | pr_debug("speaker_info: %02x\n", info->speaker_info); | 714 | pr_debug("speaker_info: %02x\n", info->speaker_info); |
717 | pr_debug("num of audio: %02x\n", info->num_of_audio_block); | 715 | pr_debug("num of audio: %02x\n", info->num_of_audio_block); |
718 | 716 | ||
719 | /* audio block */ | 717 | /* audio block */ |
720 | for (i = 0; i < info->num_of_audio_block; i++) { | 718 | for (i = 0; i < info->num_of_audio_block; i++) { |
721 | pr_debug("audio[%d] type: %02x max_ch: %02x fs: %02x sbit: " | 719 | pr_debug("audio[%d] type: %02x max_ch: %02x fs: %02x sbit: " |
722 | "%02x\n", | 720 | "%02x\n", |
723 | i, audio->type, audio->max_num_of_ch, audio->fs, | 721 | i, audio->type, audio->max_num_of_ch, audio->fs, |
724 | audio->sbit); | 722 | audio->sbit); |
725 | audio++; | 723 | audio++; |
726 | } | 724 | } |
727 | } | 725 | } |
728 | 726 | ||
729 | static const struct ps3av_monitor_quirk { | 727 | static const struct ps3av_monitor_quirk { |
730 | const char *monitor_name; | 728 | const char *monitor_name; |
731 | u32 clear_60; | 729 | u32 clear_60; |
732 | } ps3av_monitor_quirks[] = { | 730 | } ps3av_monitor_quirks[] = { |
733 | { | 731 | { |
734 | .monitor_name = "DELL 2007WFP", | 732 | .monitor_name = "DELL 2007WFP", |
735 | .clear_60 = PS3AV_RESBIT_1920x1080I | 733 | .clear_60 = PS3AV_RESBIT_1920x1080I |
736 | }, { | 734 | }, { |
737 | .monitor_name = "L226WTQ", | 735 | .monitor_name = "L226WTQ", |
738 | .clear_60 = PS3AV_RESBIT_1920x1080I | | 736 | .clear_60 = PS3AV_RESBIT_1920x1080I | |
739 | PS3AV_RESBIT_1920x1080P | 737 | PS3AV_RESBIT_1920x1080P |
740 | }, { | 738 | }, { |
741 | .monitor_name = "SyncMaster", | 739 | .monitor_name = "SyncMaster", |
742 | .clear_60 = PS3AV_RESBIT_1920x1080I | 740 | .clear_60 = PS3AV_RESBIT_1920x1080I |
743 | } | 741 | } |
744 | }; | 742 | }; |
745 | 743 | ||
746 | static void ps3av_fixup_monitor_info(struct ps3av_info_monitor *info) | 744 | static void ps3av_fixup_monitor_info(struct ps3av_info_monitor *info) |
747 | { | 745 | { |
748 | unsigned int i; | 746 | unsigned int i; |
749 | const struct ps3av_monitor_quirk *quirk; | 747 | const struct ps3av_monitor_quirk *quirk; |
750 | 748 | ||
751 | for (i = 0; i < ARRAY_SIZE(ps3av_monitor_quirks); i++) { | 749 | for (i = 0; i < ARRAY_SIZE(ps3av_monitor_quirks); i++) { |
752 | quirk = &ps3av_monitor_quirks[i]; | 750 | quirk = &ps3av_monitor_quirks[i]; |
753 | if (!strncmp(info->monitor_name, quirk->monitor_name, | 751 | if (!strncmp(info->monitor_name, quirk->monitor_name, |
754 | sizeof(info->monitor_name))) { | 752 | sizeof(info->monitor_name))) { |
755 | pr_info("%s: Applying quirk for %s\n", __func__, | 753 | pr_info("%s: Applying quirk for %s\n", __func__, |
756 | quirk->monitor_name); | 754 | quirk->monitor_name); |
757 | info->res_60.res_bits &= ~quirk->clear_60; | 755 | info->res_60.res_bits &= ~quirk->clear_60; |
758 | info->res_60.native &= ~quirk->clear_60; | 756 | info->res_60.native &= ~quirk->clear_60; |
759 | break; | 757 | break; |
760 | } | 758 | } |
761 | } | 759 | } |
762 | } | 760 | } |
763 | 761 | ||
764 | static int ps3av_auto_videomode(struct ps3av_pkt_av_get_hw_conf *av_hw_conf) | 762 | static int ps3av_auto_videomode(struct ps3av_pkt_av_get_hw_conf *av_hw_conf) |
765 | { | 763 | { |
766 | int i, res, id = 0, dvi = 0, rgb = 0; | 764 | int i, res, id = 0, dvi = 0, rgb = 0; |
767 | struct ps3av_pkt_av_get_monitor_info monitor_info; | 765 | struct ps3av_pkt_av_get_monitor_info monitor_info; |
768 | struct ps3av_info_monitor *info; | 766 | struct ps3av_info_monitor *info; |
769 | 767 | ||
770 | /* get mode id for hdmi */ | 768 | /* get mode id for hdmi */ |
771 | for (i = 0; i < av_hw_conf->num_of_hdmi && !id; i++) { | 769 | for (i = 0; i < av_hw_conf->num_of_hdmi && !id; i++) { |
772 | res = ps3av_cmd_video_get_monitor_info(&monitor_info, | 770 | res = ps3av_cmd_video_get_monitor_info(&monitor_info, |
773 | PS3AV_CMD_AVPORT_HDMI_0 + | 771 | PS3AV_CMD_AVPORT_HDMI_0 + |
774 | i); | 772 | i); |
775 | if (res < 0) | 773 | if (res < 0) |
776 | return -1; | 774 | return -1; |
777 | 775 | ||
778 | ps3av_monitor_info_dump(&monitor_info); | 776 | ps3av_monitor_info_dump(&monitor_info); |
779 | 777 | ||
780 | info = &monitor_info.info; | 778 | info = &monitor_info.info; |
781 | ps3av_fixup_monitor_info(info); | 779 | ps3av_fixup_monitor_info(info); |
782 | 780 | ||
783 | switch (info->monitor_type) { | 781 | switch (info->monitor_type) { |
784 | case PS3AV_MONITOR_TYPE_DVI: | 782 | case PS3AV_MONITOR_TYPE_DVI: |
785 | dvi = PS3AV_MODE_DVI; | 783 | dvi = PS3AV_MODE_DVI; |
786 | /* fall through */ | 784 | /* fall through */ |
787 | case PS3AV_MONITOR_TYPE_HDMI: | 785 | case PS3AV_MONITOR_TYPE_HDMI: |
788 | id = ps3av_hdmi_get_id(info); | 786 | id = ps3av_hdmi_get_id(info); |
789 | break; | 787 | break; |
790 | } | 788 | } |
791 | } | 789 | } |
792 | 790 | ||
793 | if (!id) { | 791 | if (!id) { |
794 | /* no HDMI interface or HDMI is off */ | 792 | /* no HDMI interface or HDMI is off */ |
795 | if (ps3av->region & PS3AV_REGION_60) | 793 | if (ps3av->region & PS3AV_REGION_60) |
796 | id = PS3AV_DEFAULT_AVMULTI_MODE_ID_REG_60; | 794 | id = PS3AV_DEFAULT_AVMULTI_MODE_ID_REG_60; |
797 | else | 795 | else |
798 | id = PS3AV_DEFAULT_AVMULTI_MODE_ID_REG_50; | 796 | id = PS3AV_DEFAULT_AVMULTI_MODE_ID_REG_50; |
799 | if (ps3av->region & PS3AV_REGION_RGB) | 797 | if (ps3av->region & PS3AV_REGION_RGB) |
800 | rgb = PS3AV_MODE_RGB; | 798 | rgb = PS3AV_MODE_RGB; |
801 | pr_debug("%s: Using avmulti mode %d\n", __func__, id); | 799 | pr_debug("%s: Using avmulti mode %d\n", __func__, id); |
802 | } | 800 | } |
803 | 801 | ||
804 | return id | dvi | rgb; | 802 | return id | dvi | rgb; |
805 | } | 803 | } |
806 | 804 | ||
807 | static int ps3av_get_hw_conf(struct ps3av *ps3av) | 805 | static int ps3av_get_hw_conf(struct ps3av *ps3av) |
808 | { | 806 | { |
809 | int i, j, k, res; | 807 | int i, j, k, res; |
810 | const struct ps3av_pkt_av_get_hw_conf *hw_conf; | 808 | const struct ps3av_pkt_av_get_hw_conf *hw_conf; |
811 | 809 | ||
812 | /* get av_hw_conf */ | 810 | /* get av_hw_conf */ |
813 | res = ps3av_cmd_av_get_hw_conf(&ps3av->av_hw_conf); | 811 | res = ps3av_cmd_av_get_hw_conf(&ps3av->av_hw_conf); |
814 | if (res < 0) | 812 | if (res < 0) |
815 | return -1; | 813 | return -1; |
816 | 814 | ||
817 | hw_conf = &ps3av->av_hw_conf; | 815 | hw_conf = &ps3av->av_hw_conf; |
818 | pr_debug("av_h_conf: num of hdmi: %u\n", hw_conf->num_of_hdmi); | 816 | pr_debug("av_h_conf: num of hdmi: %u\n", hw_conf->num_of_hdmi); |
819 | pr_debug("av_h_conf: num of avmulti: %u\n", hw_conf->num_of_avmulti); | 817 | pr_debug("av_h_conf: num of avmulti: %u\n", hw_conf->num_of_avmulti); |
820 | pr_debug("av_h_conf: num of spdif: %u\n", hw_conf->num_of_spdif); | 818 | pr_debug("av_h_conf: num of spdif: %u\n", hw_conf->num_of_spdif); |
821 | 819 | ||
822 | for (i = 0; i < PS3AV_HEAD_MAX; i++) | 820 | for (i = 0; i < PS3AV_HEAD_MAX; i++) |
823 | ps3av->head[i] = PS3AV_CMD_VIDEO_HEAD_A + i; | 821 | ps3av->head[i] = PS3AV_CMD_VIDEO_HEAD_A + i; |
824 | for (i = 0; i < PS3AV_OPT_PORT_MAX; i++) | 822 | for (i = 0; i < PS3AV_OPT_PORT_MAX; i++) |
825 | ps3av->opt_port[i] = PS3AV_CMD_AVPORT_SPDIF_0 + i; | 823 | ps3av->opt_port[i] = PS3AV_CMD_AVPORT_SPDIF_0 + i; |
826 | for (i = 0; i < hw_conf->num_of_hdmi; i++) | 824 | for (i = 0; i < hw_conf->num_of_hdmi; i++) |
827 | ps3av->av_port[i] = PS3AV_CMD_AVPORT_HDMI_0 + i; | 825 | ps3av->av_port[i] = PS3AV_CMD_AVPORT_HDMI_0 + i; |
828 | for (j = 0; j < hw_conf->num_of_avmulti; j++) | 826 | for (j = 0; j < hw_conf->num_of_avmulti; j++) |
829 | ps3av->av_port[i + j] = PS3AV_CMD_AVPORT_AVMULTI_0 + j; | 827 | ps3av->av_port[i + j] = PS3AV_CMD_AVPORT_AVMULTI_0 + j; |
830 | for (k = 0; k < hw_conf->num_of_spdif; k++) | 828 | for (k = 0; k < hw_conf->num_of_spdif; k++) |
831 | ps3av->av_port[i + j + k] = PS3AV_CMD_AVPORT_SPDIF_0 + k; | 829 | ps3av->av_port[i + j + k] = PS3AV_CMD_AVPORT_SPDIF_0 + k; |
832 | 830 | ||
833 | /* set all audio port */ | 831 | /* set all audio port */ |
834 | ps3av->audio_port = PS3AV_CMD_AUDIO_PORT_HDMI_0 | 832 | ps3av->audio_port = PS3AV_CMD_AUDIO_PORT_HDMI_0 |
835 | | PS3AV_CMD_AUDIO_PORT_HDMI_1 | 833 | | PS3AV_CMD_AUDIO_PORT_HDMI_1 |
836 | | PS3AV_CMD_AUDIO_PORT_AVMULTI_0 | 834 | | PS3AV_CMD_AUDIO_PORT_AVMULTI_0 |
837 | | PS3AV_CMD_AUDIO_PORT_SPDIF_0 | PS3AV_CMD_AUDIO_PORT_SPDIF_1; | 835 | | PS3AV_CMD_AUDIO_PORT_SPDIF_0 | PS3AV_CMD_AUDIO_PORT_SPDIF_1; |
838 | 836 | ||
839 | return 0; | 837 | return 0; |
840 | } | 838 | } |
841 | 839 | ||
842 | /* set mode using id */ | 840 | /* set mode using id */ |
843 | int ps3av_set_video_mode(u32 id) | 841 | int ps3av_set_video_mode(u32 id) |
844 | { | 842 | { |
845 | int size; | 843 | int size; |
846 | u32 option; | 844 | u32 option; |
847 | 845 | ||
848 | size = ARRAY_SIZE(video_mode_table); | 846 | size = ARRAY_SIZE(video_mode_table); |
849 | if ((id & PS3AV_MODE_MASK) > size - 1 || id < 0) { | 847 | if ((id & PS3AV_MODE_MASK) > size - 1 || id < 0) { |
850 | dev_dbg(&ps3av->dev->core, "%s: error id :%d\n", __func__, id); | 848 | dev_dbg(&ps3av->dev->core, "%s: error id :%d\n", __func__, id); |
851 | return -EINVAL; | 849 | return -EINVAL; |
852 | } | 850 | } |
853 | 851 | ||
854 | /* auto mode */ | 852 | /* auto mode */ |
855 | option = id & ~PS3AV_MODE_MASK; | 853 | option = id & ~PS3AV_MODE_MASK; |
856 | if ((id & PS3AV_MODE_MASK) == PS3AV_MODE_AUTO) { | 854 | if ((id & PS3AV_MODE_MASK) == PS3AV_MODE_AUTO) { |
857 | id = ps3av_auto_videomode(&ps3av->av_hw_conf); | 855 | id = ps3av_auto_videomode(&ps3av->av_hw_conf); |
858 | if (id < 1) { | 856 | if (id < 1) { |
859 | printk(KERN_ERR "%s: invalid id :%d\n", __func__, id); | 857 | printk(KERN_ERR "%s: invalid id :%d\n", __func__, id); |
860 | return -EINVAL; | 858 | return -EINVAL; |
861 | } | 859 | } |
862 | id |= option; | 860 | id |= option; |
863 | } | 861 | } |
864 | 862 | ||
865 | /* set videomode */ | 863 | /* set videomode */ |
866 | wait_for_completion(&ps3av->done); | 864 | wait_for_completion(&ps3av->done); |
867 | ps3av->ps3av_mode_old = ps3av->ps3av_mode; | 865 | ps3av->ps3av_mode_old = ps3av->ps3av_mode; |
868 | ps3av->ps3av_mode = id; | 866 | ps3av->ps3av_mode = id; |
869 | if (ps3av_set_videomode()) | 867 | if (ps3av_set_videomode()) |
870 | ps3av->ps3av_mode = ps3av->ps3av_mode_old; | 868 | ps3av->ps3av_mode = ps3av->ps3av_mode_old; |
871 | 869 | ||
872 | return 0; | 870 | return 0; |
873 | } | 871 | } |
874 | 872 | ||
875 | EXPORT_SYMBOL_GPL(ps3av_set_video_mode); | 873 | EXPORT_SYMBOL_GPL(ps3av_set_video_mode); |
876 | 874 | ||
877 | int ps3av_get_auto_mode(void) | 875 | int ps3av_get_auto_mode(void) |
878 | { | 876 | { |
879 | return ps3av_auto_videomode(&ps3av->av_hw_conf); | 877 | return ps3av_auto_videomode(&ps3av->av_hw_conf); |
880 | } | 878 | } |
881 | 879 | ||
882 | EXPORT_SYMBOL_GPL(ps3av_get_auto_mode); | 880 | EXPORT_SYMBOL_GPL(ps3av_get_auto_mode); |
883 | 881 | ||
884 | int ps3av_get_mode(void) | 882 | int ps3av_get_mode(void) |
885 | { | 883 | { |
886 | return ps3av ? ps3av->ps3av_mode : 0; | 884 | return ps3av ? ps3av->ps3av_mode : 0; |
887 | } | 885 | } |
888 | 886 | ||
889 | EXPORT_SYMBOL_GPL(ps3av_get_mode); | 887 | EXPORT_SYMBOL_GPL(ps3av_get_mode); |
890 | 888 | ||
891 | /* get resolution by video_mode */ | 889 | /* get resolution by video_mode */ |
892 | int ps3av_video_mode2res(u32 id, u32 *xres, u32 *yres) | 890 | int ps3av_video_mode2res(u32 id, u32 *xres, u32 *yres) |
893 | { | 891 | { |
894 | int size; | 892 | int size; |
895 | 893 | ||
896 | id = id & PS3AV_MODE_MASK; | 894 | id = id & PS3AV_MODE_MASK; |
897 | size = ARRAY_SIZE(video_mode_table); | 895 | size = ARRAY_SIZE(video_mode_table); |
898 | if (id > size - 1 || id < 0) { | 896 | if (id > size - 1 || id < 0) { |
899 | printk(KERN_ERR "%s: invalid mode %d\n", __func__, id); | 897 | printk(KERN_ERR "%s: invalid mode %d\n", __func__, id); |
900 | return -EINVAL; | 898 | return -EINVAL; |
901 | } | 899 | } |
902 | *xres = video_mode_table[id].x; | 900 | *xres = video_mode_table[id].x; |
903 | *yres = video_mode_table[id].y; | 901 | *yres = video_mode_table[id].y; |
904 | return 0; | 902 | return 0; |
905 | } | 903 | } |
906 | 904 | ||
907 | EXPORT_SYMBOL_GPL(ps3av_video_mode2res); | 905 | EXPORT_SYMBOL_GPL(ps3av_video_mode2res); |
908 | 906 | ||
909 | /* mute */ | 907 | /* mute */ |
910 | int ps3av_video_mute(int mute) | 908 | int ps3av_video_mute(int mute) |
911 | { | 909 | { |
912 | return ps3av_set_av_video_mute(mute ? PS3AV_CMD_MUTE_ON | 910 | return ps3av_set_av_video_mute(mute ? PS3AV_CMD_MUTE_ON |
913 | : PS3AV_CMD_MUTE_OFF); | 911 | : PS3AV_CMD_MUTE_OFF); |
914 | } | 912 | } |
915 | 913 | ||
916 | EXPORT_SYMBOL_GPL(ps3av_video_mute); | 914 | EXPORT_SYMBOL_GPL(ps3av_video_mute); |
917 | 915 | ||
918 | /* mute analog output only */ | 916 | /* mute analog output only */ |
919 | int ps3av_audio_mute_analog(int mute) | 917 | int ps3av_audio_mute_analog(int mute) |
920 | { | 918 | { |
921 | int i, res; | 919 | int i, res; |
922 | 920 | ||
923 | for (i = 0; i < ps3av->av_hw_conf.num_of_avmulti; i++) { | 921 | for (i = 0; i < ps3av->av_hw_conf.num_of_avmulti; i++) { |
924 | res = ps3av_cmd_av_audio_mute(1, | 922 | res = ps3av_cmd_av_audio_mute(1, |
925 | &ps3av->av_port[i + ps3av->av_hw_conf.num_of_hdmi], | 923 | &ps3av->av_port[i + ps3av->av_hw_conf.num_of_hdmi], |
926 | mute); | 924 | mute); |
927 | if (res < 0) | 925 | if (res < 0) |
928 | return -1; | 926 | return -1; |
929 | } | 927 | } |
930 | return 0; | 928 | return 0; |
931 | } | 929 | } |
932 | EXPORT_SYMBOL_GPL(ps3av_audio_mute_analog); | 930 | EXPORT_SYMBOL_GPL(ps3av_audio_mute_analog); |
933 | 931 | ||
934 | int ps3av_audio_mute(int mute) | 932 | int ps3av_audio_mute(int mute) |
935 | { | 933 | { |
936 | return ps3av_set_audio_mute(mute ? PS3AV_CMD_MUTE_ON | 934 | return ps3av_set_audio_mute(mute ? PS3AV_CMD_MUTE_ON |
937 | : PS3AV_CMD_MUTE_OFF); | 935 | : PS3AV_CMD_MUTE_OFF); |
938 | } | 936 | } |
939 | 937 | ||
940 | EXPORT_SYMBOL_GPL(ps3av_audio_mute); | 938 | EXPORT_SYMBOL_GPL(ps3av_audio_mute); |
941 | |||
942 | void ps3av_register_flip_ctl(void (*flip_ctl)(int on, void *data), | ||
943 | void *flip_data) | ||
944 | { | ||
945 | mutex_lock(&ps3av->mutex); | ||
946 | ps3av->flip_ctl = flip_ctl; | ||
947 | ps3av->flip_data = flip_data; | ||
948 | mutex_unlock(&ps3av->mutex); | ||
949 | } | ||
950 | EXPORT_SYMBOL_GPL(ps3av_register_flip_ctl); | ||
951 | |||
952 | void ps3av_flip_ctl(int on) | ||
953 | { | ||
954 | mutex_lock(&ps3av->mutex); | ||
955 | if (ps3av->flip_ctl) | ||
956 | ps3av->flip_ctl(on, ps3av->flip_data); | ||
957 | mutex_unlock(&ps3av->mutex); | ||
958 | } | ||
959 | 939 | ||
960 | static int ps3av_probe(struct ps3_system_bus_device *dev) | 940 | static int ps3av_probe(struct ps3_system_bus_device *dev) |
961 | { | 941 | { |
962 | int res; | 942 | int res; |
963 | u32 id; | 943 | u32 id; |
964 | 944 | ||
965 | dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__); | 945 | dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__); |
966 | dev_dbg(&dev->core, " timeout=%d\n", timeout); | 946 | dev_dbg(&dev->core, " timeout=%d\n", timeout); |
967 | 947 | ||
968 | if (ps3av) { | 948 | if (ps3av) { |
969 | dev_err(&dev->core, "Only one ps3av device is supported\n"); | 949 | dev_err(&dev->core, "Only one ps3av device is supported\n"); |
970 | return -EBUSY; | 950 | return -EBUSY; |
971 | } | 951 | } |
972 | 952 | ||
973 | ps3av = kzalloc(sizeof(*ps3av), GFP_KERNEL); | 953 | ps3av = kzalloc(sizeof(*ps3av), GFP_KERNEL); |
974 | if (!ps3av) | 954 | if (!ps3av) |
975 | return -ENOMEM; | 955 | return -ENOMEM; |
976 | 956 | ||
977 | mutex_init(&ps3av->mutex); | 957 | mutex_init(&ps3av->mutex); |
978 | ps3av->ps3av_mode = PS3AV_MODE_AUTO; | 958 | ps3av->ps3av_mode = PS3AV_MODE_AUTO; |
979 | ps3av->dev = dev; | 959 | ps3av->dev = dev; |
980 | 960 | ||
981 | INIT_WORK(&ps3av->work, ps3avd); | 961 | INIT_WORK(&ps3av->work, ps3avd); |
982 | init_completion(&ps3av->done); | 962 | init_completion(&ps3av->done); |
983 | complete(&ps3av->done); | 963 | complete(&ps3av->done); |
984 | ps3av->wq = create_singlethread_workqueue("ps3avd"); | 964 | ps3av->wq = create_singlethread_workqueue("ps3avd"); |
985 | if (!ps3av->wq) | 965 | if (!ps3av->wq) |
986 | goto fail; | 966 | goto fail; |
987 | 967 | ||
988 | switch (ps3_os_area_get_av_multi_out()) { | 968 | switch (ps3_os_area_get_av_multi_out()) { |
989 | case PS3_PARAM_AV_MULTI_OUT_NTSC: | 969 | case PS3_PARAM_AV_MULTI_OUT_NTSC: |
990 | ps3av->region = PS3AV_REGION_60; | 970 | ps3av->region = PS3AV_REGION_60; |
991 | break; | 971 | break; |
992 | case PS3_PARAM_AV_MULTI_OUT_PAL_YCBCR: | 972 | case PS3_PARAM_AV_MULTI_OUT_PAL_YCBCR: |
993 | case PS3_PARAM_AV_MULTI_OUT_SECAM: | 973 | case PS3_PARAM_AV_MULTI_OUT_SECAM: |
994 | ps3av->region = PS3AV_REGION_50; | 974 | ps3av->region = PS3AV_REGION_50; |
995 | break; | 975 | break; |
996 | case PS3_PARAM_AV_MULTI_OUT_PAL_RGB: | 976 | case PS3_PARAM_AV_MULTI_OUT_PAL_RGB: |
997 | ps3av->region = PS3AV_REGION_50 | PS3AV_REGION_RGB; | 977 | ps3av->region = PS3AV_REGION_50 | PS3AV_REGION_RGB; |
998 | break; | 978 | break; |
999 | default: | 979 | default: |
1000 | ps3av->region = PS3AV_REGION_60; | 980 | ps3av->region = PS3AV_REGION_60; |
1001 | break; | 981 | break; |
1002 | } | 982 | } |
1003 | 983 | ||
1004 | /* init avsetting modules */ | 984 | /* init avsetting modules */ |
1005 | res = ps3av_cmd_init(); | 985 | res = ps3av_cmd_init(); |
1006 | if (res < 0) | 986 | if (res < 0) |
1007 | printk(KERN_ERR "%s: ps3av_cmd_init failed %d\n", __func__, | 987 | printk(KERN_ERR "%s: ps3av_cmd_init failed %d\n", __func__, |
1008 | res); | 988 | res); |
1009 | 989 | ||
1010 | ps3av_get_hw_conf(ps3av); | 990 | ps3av_get_hw_conf(ps3av); |
1011 | 991 | ||
1012 | #ifdef CONFIG_FB | 992 | #ifdef CONFIG_FB |
1013 | if (fb_mode_option && !strcmp(fb_mode_option, "safe")) | 993 | if (fb_mode_option && !strcmp(fb_mode_option, "safe")) |
1014 | safe_mode = 1; | 994 | safe_mode = 1; |
1015 | #endif /* CONFIG_FB */ | 995 | #endif /* CONFIG_FB */ |
1016 | id = ps3av_auto_videomode(&ps3av->av_hw_conf); | 996 | id = ps3av_auto_videomode(&ps3av->av_hw_conf); |
1017 | safe_mode = 0; | 997 | safe_mode = 0; |
1018 | 998 | ||
1019 | mutex_lock(&ps3av->mutex); | 999 | mutex_lock(&ps3av->mutex); |
1020 | ps3av->ps3av_mode = id; | 1000 | ps3av->ps3av_mode = id; |
1021 | mutex_unlock(&ps3av->mutex); | 1001 | mutex_unlock(&ps3av->mutex); |
1022 | 1002 | ||
1023 | dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__); | 1003 | dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__); |
1024 | 1004 | ||
1025 | return 0; | 1005 | return 0; |
1026 | 1006 | ||
1027 | fail: | 1007 | fail: |
1028 | kfree(ps3av); | 1008 | kfree(ps3av); |
1029 | ps3av = NULL; | 1009 | ps3av = NULL; |
1030 | return -ENOMEM; | 1010 | return -ENOMEM; |
1031 | } | 1011 | } |
1032 | 1012 | ||
1033 | static int ps3av_remove(struct ps3_system_bus_device *dev) | 1013 | static int ps3av_remove(struct ps3_system_bus_device *dev) |
1034 | { | 1014 | { |
1035 | dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__); | 1015 | dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__); |
1036 | if (ps3av) { | 1016 | if (ps3av) { |
1037 | ps3av_cmd_fin(); | 1017 | ps3av_cmd_fin(); |
1038 | if (ps3av->wq) | 1018 | if (ps3av->wq) |
1039 | destroy_workqueue(ps3av->wq); | 1019 | destroy_workqueue(ps3av->wq); |
1040 | kfree(ps3av); | 1020 | kfree(ps3av); |
1041 | ps3av = NULL; | 1021 | ps3av = NULL; |
1042 | } | 1022 | } |
1043 | 1023 | ||
1044 | dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__); | 1024 | dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__); |
1045 | return 0; | 1025 | return 0; |
1046 | } | 1026 | } |
1047 | 1027 | ||
1048 | static void ps3av_shutdown(struct ps3_system_bus_device *dev) | 1028 | static void ps3av_shutdown(struct ps3_system_bus_device *dev) |
1049 | { | 1029 | { |
1050 | dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__); | 1030 | dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__); |
1051 | ps3av_remove(dev); | 1031 | ps3av_remove(dev); |
1052 | dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__); | 1032 | dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__); |
1053 | } | 1033 | } |
1054 | 1034 | ||
1055 | static struct ps3_vuart_port_driver ps3av_driver = { | 1035 | static struct ps3_vuart_port_driver ps3av_driver = { |
1056 | .core.match_id = PS3_MATCH_ID_AV_SETTINGS, | 1036 | .core.match_id = PS3_MATCH_ID_AV_SETTINGS, |
1057 | .core.core.name = "ps3_av", | 1037 | .core.core.name = "ps3_av", |
1058 | .probe = ps3av_probe, | 1038 | .probe = ps3av_probe, |
1059 | .remove = ps3av_remove, | 1039 | .remove = ps3av_remove, |
1060 | .shutdown = ps3av_shutdown, | 1040 | .shutdown = ps3av_shutdown, |
1061 | }; | 1041 | }; |
1062 | 1042 | ||
1063 | static int ps3av_module_init(void) | 1043 | static int ps3av_module_init(void) |
1064 | { | 1044 | { |
1065 | int error; | 1045 | int error; |
1066 | 1046 | ||
1067 | if (!firmware_has_feature(FW_FEATURE_PS3_LV1)) | 1047 | if (!firmware_has_feature(FW_FEATURE_PS3_LV1)) |
1068 | return -ENODEV; | 1048 | return -ENODEV; |
1069 | 1049 | ||
1070 | pr_debug(" -> %s:%d\n", __func__, __LINE__); | 1050 | pr_debug(" -> %s:%d\n", __func__, __LINE__); |
1071 | 1051 | ||
1072 | error = ps3_vuart_port_driver_register(&ps3av_driver); | 1052 | error = ps3_vuart_port_driver_register(&ps3av_driver); |
1073 | if (error) { | 1053 | if (error) { |
1074 | printk(KERN_ERR | 1054 | printk(KERN_ERR |
1075 | "%s: ps3_vuart_port_driver_register failed %d\n", | 1055 | "%s: ps3_vuart_port_driver_register failed %d\n", |
1076 | __func__, error); | 1056 | __func__, error); |
1077 | return error; | 1057 | return error; |
1078 | } | 1058 | } |
1079 | 1059 | ||
1080 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | 1060 | pr_debug(" <- %s:%d\n", __func__, __LINE__); |
1081 | return error; | 1061 | return error; |
1082 | } | 1062 | } |
1083 | 1063 | ||
1084 | static void __exit ps3av_module_exit(void) | 1064 | static void __exit ps3av_module_exit(void) |
1085 | { | 1065 | { |
1086 | pr_debug(" -> %s:%d\n", __func__, __LINE__); | 1066 | pr_debug(" -> %s:%d\n", __func__, __LINE__); |
1087 | ps3_vuart_port_driver_unregister(&ps3av_driver); | 1067 | ps3_vuart_port_driver_unregister(&ps3av_driver); |
1088 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | 1068 | pr_debug(" <- %s:%d\n", __func__, __LINE__); |
1089 | } | 1069 | } |
1090 | 1070 | ||
1091 | subsys_initcall(ps3av_module_init); | 1071 | subsys_initcall(ps3av_module_init); |
1092 | module_exit(ps3av_module_exit); | 1072 | module_exit(ps3av_module_exit); |
1093 | 1073 | ||
1094 | MODULE_LICENSE("GPL v2"); | 1074 | MODULE_LICENSE("GPL v2"); |
1095 | MODULE_DESCRIPTION("PS3 AV Settings Driver"); | 1075 | MODULE_DESCRIPTION("PS3 AV Settings Driver"); |
1096 | MODULE_AUTHOR("Sony Computer Entertainment Inc."); | 1076 | MODULE_AUTHOR("Sony Computer Entertainment Inc."); |
1097 | MODULE_ALIAS(PS3_MODULE_ALIAS_AV_SETTINGS); | 1077 | MODULE_ALIAS(PS3_MODULE_ALIAS_AV_SETTINGS); |
1098 | 1078 |
drivers/ps3/ps3av_cmd.c
1 | /* | 1 | /* |
2 | * Copyright (C) 2006 Sony Computer Entertainment Inc. | 2 | * Copyright (C) 2006 Sony Computer Entertainment Inc. |
3 | * Copyright 2006, 2007 Sony Corporation | 3 | * Copyright 2006, 2007 Sony Corporation |
4 | * | 4 | * |
5 | * AV backend support for PS3 | 5 | * AV backend support for PS3 |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify it | 7 | * This program is free software; you can redistribute it and/or modify it |
8 | * under the terms of the GNU General Public License as published | 8 | * under the terms of the GNU General Public License as published |
9 | * by the Free Software Foundation; version 2 of the License. | 9 | * by the Free Software Foundation; version 2 of the License. |
10 | * | 10 | * |
11 | * This program is distributed in the hope that it will be useful, but | 11 | * This program is distributed in the hope that it will be useful, but |
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | 12 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
14 | * General Public License for more details. | 14 | * General Public License for more details. |
15 | * | 15 | * |
16 | * You should have received a copy of the GNU General Public License along | 16 | * You should have received a copy of the GNU General Public License along |
17 | * with this program; if not, write to the Free Software Foundation, Inc., | 17 | * with this program; if not, write to the Free Software Foundation, Inc., |
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
19 | */ | 19 | */ |
20 | 20 | ||
21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
22 | #include <linux/kernel.h> | 22 | #include <linux/kernel.h> |
23 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
24 | #include <asm/ps3av.h> | 24 | #include <asm/ps3av.h> |
25 | #include <asm/ps3fb.h> | 25 | #include <asm/ps3fb.h> |
26 | #include <asm/ps3.h> | 26 | #include <asm/ps3.h> |
27 | 27 | ||
28 | #include "vuart.h" | 28 | #include "vuart.h" |
29 | 29 | ||
30 | static const struct video_fmt { | 30 | static const struct video_fmt { |
31 | u32 format; | 31 | u32 format; |
32 | u32 order; | 32 | u32 order; |
33 | } ps3av_video_fmt_table[] = { | 33 | } ps3av_video_fmt_table[] = { |
34 | { PS3AV_CMD_VIDEO_FORMAT_ARGB_8BIT, PS3AV_CMD_VIDEO_ORDER_RGB }, | 34 | { PS3AV_CMD_VIDEO_FORMAT_ARGB_8BIT, PS3AV_CMD_VIDEO_ORDER_RGB }, |
35 | { PS3AV_CMD_VIDEO_FORMAT_ARGB_8BIT, PS3AV_CMD_VIDEO_ORDER_BGR }, | 35 | { PS3AV_CMD_VIDEO_FORMAT_ARGB_8BIT, PS3AV_CMD_VIDEO_ORDER_BGR }, |
36 | }; | 36 | }; |
37 | 37 | ||
38 | static const struct { | 38 | static const struct { |
39 | int cs; | 39 | int cs; |
40 | u32 av; | 40 | u32 av; |
41 | u32 bl; | 41 | u32 bl; |
42 | } ps3av_cs_video2av_table[] = { | 42 | } ps3av_cs_video2av_table[] = { |
43 | { | 43 | { |
44 | .cs = PS3AV_CMD_VIDEO_CS_RGB_8, | 44 | .cs = PS3AV_CMD_VIDEO_CS_RGB_8, |
45 | .av = PS3AV_CMD_AV_CS_RGB_8, | 45 | .av = PS3AV_CMD_AV_CS_RGB_8, |
46 | .bl = PS3AV_CMD_AV_CS_8 | 46 | .bl = PS3AV_CMD_AV_CS_8 |
47 | }, { | 47 | }, { |
48 | .cs = PS3AV_CMD_VIDEO_CS_RGB_10, | 48 | .cs = PS3AV_CMD_VIDEO_CS_RGB_10, |
49 | .av = PS3AV_CMD_AV_CS_RGB_8, | 49 | .av = PS3AV_CMD_AV_CS_RGB_8, |
50 | .bl = PS3AV_CMD_AV_CS_8 | 50 | .bl = PS3AV_CMD_AV_CS_8 |
51 | }, { | 51 | }, { |
52 | .cs = PS3AV_CMD_VIDEO_CS_RGB_12, | 52 | .cs = PS3AV_CMD_VIDEO_CS_RGB_12, |
53 | .av = PS3AV_CMD_AV_CS_RGB_8, | 53 | .av = PS3AV_CMD_AV_CS_RGB_8, |
54 | .bl = PS3AV_CMD_AV_CS_8 | 54 | .bl = PS3AV_CMD_AV_CS_8 |
55 | }, { | 55 | }, { |
56 | .cs = PS3AV_CMD_VIDEO_CS_YUV444_8, | 56 | .cs = PS3AV_CMD_VIDEO_CS_YUV444_8, |
57 | .av = PS3AV_CMD_AV_CS_YUV444_8, | 57 | .av = PS3AV_CMD_AV_CS_YUV444_8, |
58 | .bl = PS3AV_CMD_AV_CS_8 | 58 | .bl = PS3AV_CMD_AV_CS_8 |
59 | }, { | 59 | }, { |
60 | .cs = PS3AV_CMD_VIDEO_CS_YUV444_10, | 60 | .cs = PS3AV_CMD_VIDEO_CS_YUV444_10, |
61 | .av = PS3AV_CMD_AV_CS_YUV444_8, | 61 | .av = PS3AV_CMD_AV_CS_YUV444_8, |
62 | .bl = PS3AV_CMD_AV_CS_10 | 62 | .bl = PS3AV_CMD_AV_CS_10 |
63 | }, { | 63 | }, { |
64 | .cs = PS3AV_CMD_VIDEO_CS_YUV444_12, | 64 | .cs = PS3AV_CMD_VIDEO_CS_YUV444_12, |
65 | .av = PS3AV_CMD_AV_CS_YUV444_8, | 65 | .av = PS3AV_CMD_AV_CS_YUV444_8, |
66 | .bl = PS3AV_CMD_AV_CS_10 | 66 | .bl = PS3AV_CMD_AV_CS_10 |
67 | }, { | 67 | }, { |
68 | .cs = PS3AV_CMD_VIDEO_CS_YUV422_8, | 68 | .cs = PS3AV_CMD_VIDEO_CS_YUV422_8, |
69 | .av = PS3AV_CMD_AV_CS_YUV422_8, | 69 | .av = PS3AV_CMD_AV_CS_YUV422_8, |
70 | .bl = PS3AV_CMD_AV_CS_10 | 70 | .bl = PS3AV_CMD_AV_CS_10 |
71 | }, { | 71 | }, { |
72 | .cs = PS3AV_CMD_VIDEO_CS_YUV422_10, | 72 | .cs = PS3AV_CMD_VIDEO_CS_YUV422_10, |
73 | .av = PS3AV_CMD_AV_CS_YUV422_8, | 73 | .av = PS3AV_CMD_AV_CS_YUV422_8, |
74 | .bl = PS3AV_CMD_AV_CS_10 | 74 | .bl = PS3AV_CMD_AV_CS_10 |
75 | }, { | 75 | }, { |
76 | .cs = PS3AV_CMD_VIDEO_CS_YUV422_12, | 76 | .cs = PS3AV_CMD_VIDEO_CS_YUV422_12, |
77 | .av = PS3AV_CMD_AV_CS_YUV422_8, | 77 | .av = PS3AV_CMD_AV_CS_YUV422_8, |
78 | .bl = PS3AV_CMD_AV_CS_12 | 78 | .bl = PS3AV_CMD_AV_CS_12 |
79 | }, { | 79 | }, { |
80 | .cs = PS3AV_CMD_VIDEO_CS_XVYCC_8, | 80 | .cs = PS3AV_CMD_VIDEO_CS_XVYCC_8, |
81 | .av = PS3AV_CMD_AV_CS_XVYCC_8, | 81 | .av = PS3AV_CMD_AV_CS_XVYCC_8, |
82 | .bl = PS3AV_CMD_AV_CS_12 | 82 | .bl = PS3AV_CMD_AV_CS_12 |
83 | }, { | 83 | }, { |
84 | .cs = PS3AV_CMD_VIDEO_CS_XVYCC_10, | 84 | .cs = PS3AV_CMD_VIDEO_CS_XVYCC_10, |
85 | .av = PS3AV_CMD_AV_CS_XVYCC_8, | 85 | .av = PS3AV_CMD_AV_CS_XVYCC_8, |
86 | .bl = PS3AV_CMD_AV_CS_12 | 86 | .bl = PS3AV_CMD_AV_CS_12 |
87 | }, { | 87 | }, { |
88 | .cs = PS3AV_CMD_VIDEO_CS_XVYCC_12, | 88 | .cs = PS3AV_CMD_VIDEO_CS_XVYCC_12, |
89 | .av = PS3AV_CMD_AV_CS_XVYCC_8, | 89 | .av = PS3AV_CMD_AV_CS_XVYCC_8, |
90 | .bl = PS3AV_CMD_AV_CS_12 | 90 | .bl = PS3AV_CMD_AV_CS_12 |
91 | } | 91 | } |
92 | }; | 92 | }; |
93 | 93 | ||
94 | static u32 ps3av_cs_video2av(int cs) | 94 | static u32 ps3av_cs_video2av(int cs) |
95 | { | 95 | { |
96 | unsigned int i; | 96 | unsigned int i; |
97 | 97 | ||
98 | for (i = 0; i < ARRAY_SIZE(ps3av_cs_video2av_table); i++) | 98 | for (i = 0; i < ARRAY_SIZE(ps3av_cs_video2av_table); i++) |
99 | if (ps3av_cs_video2av_table[i].cs == cs) | 99 | if (ps3av_cs_video2av_table[i].cs == cs) |
100 | return ps3av_cs_video2av_table[i].av; | 100 | return ps3av_cs_video2av_table[i].av; |
101 | 101 | ||
102 | return PS3AV_CMD_AV_CS_RGB_8; | 102 | return PS3AV_CMD_AV_CS_RGB_8; |
103 | } | 103 | } |
104 | 104 | ||
105 | static u32 ps3av_cs_video2av_bitlen(int cs) | 105 | static u32 ps3av_cs_video2av_bitlen(int cs) |
106 | { | 106 | { |
107 | unsigned int i; | 107 | unsigned int i; |
108 | 108 | ||
109 | for (i = 0; i < ARRAY_SIZE(ps3av_cs_video2av_table); i++) | 109 | for (i = 0; i < ARRAY_SIZE(ps3av_cs_video2av_table); i++) |
110 | if (ps3av_cs_video2av_table[i].cs == cs) | 110 | if (ps3av_cs_video2av_table[i].cs == cs) |
111 | return ps3av_cs_video2av_table[i].bl; | 111 | return ps3av_cs_video2av_table[i].bl; |
112 | 112 | ||
113 | return PS3AV_CMD_AV_CS_8; | 113 | return PS3AV_CMD_AV_CS_8; |
114 | } | 114 | } |
115 | 115 | ||
116 | static const struct { | 116 | static const struct { |
117 | int vid; | 117 | int vid; |
118 | u32 av; | 118 | u32 av; |
119 | } ps3av_vid_video2av_table[] = { | 119 | } ps3av_vid_video2av_table[] = { |
120 | { PS3AV_CMD_VIDEO_VID_480I, PS3AV_CMD_AV_VID_480I }, | 120 | { PS3AV_CMD_VIDEO_VID_480I, PS3AV_CMD_AV_VID_480I }, |
121 | { PS3AV_CMD_VIDEO_VID_480P, PS3AV_CMD_AV_VID_480P }, | 121 | { PS3AV_CMD_VIDEO_VID_480P, PS3AV_CMD_AV_VID_480P }, |
122 | { PS3AV_CMD_VIDEO_VID_576I, PS3AV_CMD_AV_VID_576I }, | 122 | { PS3AV_CMD_VIDEO_VID_576I, PS3AV_CMD_AV_VID_576I }, |
123 | { PS3AV_CMD_VIDEO_VID_576P, PS3AV_CMD_AV_VID_576P }, | 123 | { PS3AV_CMD_VIDEO_VID_576P, PS3AV_CMD_AV_VID_576P }, |
124 | { PS3AV_CMD_VIDEO_VID_1080I_60HZ, PS3AV_CMD_AV_VID_1080I_60HZ }, | 124 | { PS3AV_CMD_VIDEO_VID_1080I_60HZ, PS3AV_CMD_AV_VID_1080I_60HZ }, |
125 | { PS3AV_CMD_VIDEO_VID_720P_60HZ, PS3AV_CMD_AV_VID_720P_60HZ }, | 125 | { PS3AV_CMD_VIDEO_VID_720P_60HZ, PS3AV_CMD_AV_VID_720P_60HZ }, |
126 | { PS3AV_CMD_VIDEO_VID_1080P_60HZ, PS3AV_CMD_AV_VID_1080P_60HZ }, | 126 | { PS3AV_CMD_VIDEO_VID_1080P_60HZ, PS3AV_CMD_AV_VID_1080P_60HZ }, |
127 | { PS3AV_CMD_VIDEO_VID_1080I_50HZ, PS3AV_CMD_AV_VID_1080I_50HZ }, | 127 | { PS3AV_CMD_VIDEO_VID_1080I_50HZ, PS3AV_CMD_AV_VID_1080I_50HZ }, |
128 | { PS3AV_CMD_VIDEO_VID_720P_50HZ, PS3AV_CMD_AV_VID_720P_50HZ }, | 128 | { PS3AV_CMD_VIDEO_VID_720P_50HZ, PS3AV_CMD_AV_VID_720P_50HZ }, |
129 | { PS3AV_CMD_VIDEO_VID_1080P_50HZ, PS3AV_CMD_AV_VID_1080P_50HZ }, | 129 | { PS3AV_CMD_VIDEO_VID_1080P_50HZ, PS3AV_CMD_AV_VID_1080P_50HZ }, |
130 | { PS3AV_CMD_VIDEO_VID_WXGA, PS3AV_CMD_AV_VID_WXGA }, | 130 | { PS3AV_CMD_VIDEO_VID_WXGA, PS3AV_CMD_AV_VID_WXGA }, |
131 | { PS3AV_CMD_VIDEO_VID_SXGA, PS3AV_CMD_AV_VID_SXGA }, | 131 | { PS3AV_CMD_VIDEO_VID_SXGA, PS3AV_CMD_AV_VID_SXGA }, |
132 | { PS3AV_CMD_VIDEO_VID_WUXGA, PS3AV_CMD_AV_VID_WUXGA } | 132 | { PS3AV_CMD_VIDEO_VID_WUXGA, PS3AV_CMD_AV_VID_WUXGA } |
133 | }; | 133 | }; |
134 | 134 | ||
135 | static u32 ps3av_vid_video2av(int vid) | 135 | static u32 ps3av_vid_video2av(int vid) |
136 | { | 136 | { |
137 | unsigned int i; | 137 | unsigned int i; |
138 | 138 | ||
139 | for (i = 0; i < ARRAY_SIZE(ps3av_vid_video2av_table); i++) | 139 | for (i = 0; i < ARRAY_SIZE(ps3av_vid_video2av_table); i++) |
140 | if (ps3av_vid_video2av_table[i].vid == vid) | 140 | if (ps3av_vid_video2av_table[i].vid == vid) |
141 | return ps3av_vid_video2av_table[i].av; | 141 | return ps3av_vid_video2av_table[i].av; |
142 | 142 | ||
143 | return PS3AV_CMD_AV_VID_480P; | 143 | return PS3AV_CMD_AV_VID_480P; |
144 | } | 144 | } |
145 | 145 | ||
146 | static int ps3av_hdmi_range(void) | 146 | static int ps3av_hdmi_range(void) |
147 | { | 147 | { |
148 | if (ps3_compare_firmware_version(1, 8, 0) < 0) | 148 | if (ps3_compare_firmware_version(1, 8, 0) < 0) |
149 | return 0; | 149 | return 0; |
150 | else | 150 | else |
151 | return 1; /* supported */ | 151 | return 1; /* supported */ |
152 | } | 152 | } |
153 | 153 | ||
154 | int ps3av_cmd_init(void) | 154 | int ps3av_cmd_init(void) |
155 | { | 155 | { |
156 | int res; | 156 | int res; |
157 | struct ps3av_pkt_av_init av_init; | 157 | struct ps3av_pkt_av_init av_init; |
158 | struct ps3av_pkt_video_init video_init; | 158 | struct ps3av_pkt_video_init video_init; |
159 | struct ps3av_pkt_audio_init audio_init; | 159 | struct ps3av_pkt_audio_init audio_init; |
160 | 160 | ||
161 | /* video init */ | 161 | /* video init */ |
162 | memset(&video_init, 0, sizeof(video_init)); | 162 | memset(&video_init, 0, sizeof(video_init)); |
163 | 163 | ||
164 | res = ps3av_do_pkt(PS3AV_CID_VIDEO_INIT, sizeof(video_init.send_hdr), | 164 | res = ps3av_do_pkt(PS3AV_CID_VIDEO_INIT, sizeof(video_init.send_hdr), |
165 | sizeof(video_init), &video_init.send_hdr); | 165 | sizeof(video_init), &video_init.send_hdr); |
166 | if (res < 0) | 166 | if (res < 0) |
167 | return res; | 167 | return res; |
168 | 168 | ||
169 | res = get_status(&video_init); | 169 | res = get_status(&video_init); |
170 | if (res) { | 170 | if (res) { |
171 | printk(KERN_ERR "PS3AV_CID_VIDEO_INIT: failed %x\n", res); | 171 | printk(KERN_ERR "PS3AV_CID_VIDEO_INIT: failed %x\n", res); |
172 | return res; | 172 | return res; |
173 | } | 173 | } |
174 | 174 | ||
175 | /* audio init */ | 175 | /* audio init */ |
176 | memset(&audio_init, 0, sizeof(audio_init)); | 176 | memset(&audio_init, 0, sizeof(audio_init)); |
177 | 177 | ||
178 | res = ps3av_do_pkt(PS3AV_CID_AUDIO_INIT, sizeof(audio_init.send_hdr), | 178 | res = ps3av_do_pkt(PS3AV_CID_AUDIO_INIT, sizeof(audio_init.send_hdr), |
179 | sizeof(audio_init), &audio_init.send_hdr); | 179 | sizeof(audio_init), &audio_init.send_hdr); |
180 | if (res < 0) | 180 | if (res < 0) |
181 | return res; | 181 | return res; |
182 | 182 | ||
183 | res = get_status(&audio_init); | 183 | res = get_status(&audio_init); |
184 | if (res) { | 184 | if (res) { |
185 | printk(KERN_ERR "PS3AV_CID_AUDIO_INIT: failed %x\n", res); | 185 | printk(KERN_ERR "PS3AV_CID_AUDIO_INIT: failed %x\n", res); |
186 | return res; | 186 | return res; |
187 | } | 187 | } |
188 | 188 | ||
189 | /* av init */ | 189 | /* av init */ |
190 | memset(&av_init, 0, sizeof(av_init)); | 190 | memset(&av_init, 0, sizeof(av_init)); |
191 | av_init.event_bit = 0; | 191 | av_init.event_bit = 0; |
192 | 192 | ||
193 | res = ps3av_do_pkt(PS3AV_CID_AV_INIT, sizeof(av_init), sizeof(av_init), | 193 | res = ps3av_do_pkt(PS3AV_CID_AV_INIT, sizeof(av_init), sizeof(av_init), |
194 | &av_init.send_hdr); | 194 | &av_init.send_hdr); |
195 | if (res < 0) | 195 | if (res < 0) |
196 | return res; | 196 | return res; |
197 | 197 | ||
198 | res = get_status(&av_init); | 198 | res = get_status(&av_init); |
199 | if (res) | 199 | if (res) |
200 | printk(KERN_ERR "PS3AV_CID_AV_INIT: failed %x\n", res); | 200 | printk(KERN_ERR "PS3AV_CID_AV_INIT: failed %x\n", res); |
201 | 201 | ||
202 | return res; | 202 | return res; |
203 | } | 203 | } |
204 | 204 | ||
205 | int ps3av_cmd_fin(void) | 205 | int ps3av_cmd_fin(void) |
206 | { | 206 | { |
207 | int res; | 207 | int res; |
208 | struct ps3av_pkt_av_fin av_fin; | 208 | struct ps3av_pkt_av_fin av_fin; |
209 | 209 | ||
210 | memset(&av_fin, 0, sizeof(av_fin)); | 210 | memset(&av_fin, 0, sizeof(av_fin)); |
211 | 211 | ||
212 | res = ps3av_do_pkt(PS3AV_CID_AV_FIN, sizeof(av_fin.send_hdr), | 212 | res = ps3av_do_pkt(PS3AV_CID_AV_FIN, sizeof(av_fin.send_hdr), |
213 | sizeof(av_fin), &av_fin.send_hdr); | 213 | sizeof(av_fin), &av_fin.send_hdr); |
214 | if (res < 0) | 214 | if (res < 0) |
215 | return res; | 215 | return res; |
216 | 216 | ||
217 | res = get_status(&av_fin); | 217 | res = get_status(&av_fin); |
218 | if (res) | 218 | if (res) |
219 | printk(KERN_ERR "PS3AV_CID_AV_FIN: failed %x\n", res); | 219 | printk(KERN_ERR "PS3AV_CID_AV_FIN: failed %x\n", res); |
220 | 220 | ||
221 | return res; | 221 | return res; |
222 | } | 222 | } |
223 | 223 | ||
224 | int ps3av_cmd_av_video_mute(int num_of_port, u32 *port, u32 mute) | 224 | int ps3av_cmd_av_video_mute(int num_of_port, u32 *port, u32 mute) |
225 | { | 225 | { |
226 | int i, send_len, res; | 226 | int i, send_len, res; |
227 | struct ps3av_pkt_av_video_mute av_video_mute; | 227 | struct ps3av_pkt_av_video_mute av_video_mute; |
228 | 228 | ||
229 | if (num_of_port > PS3AV_MUTE_PORT_MAX) | 229 | if (num_of_port > PS3AV_MUTE_PORT_MAX) |
230 | return -EINVAL; | 230 | return -EINVAL; |
231 | 231 | ||
232 | memset(&av_video_mute, 0, sizeof(av_video_mute)); | 232 | memset(&av_video_mute, 0, sizeof(av_video_mute)); |
233 | for (i = 0; i < num_of_port; i++) { | 233 | for (i = 0; i < num_of_port; i++) { |
234 | av_video_mute.mute[i].avport = port[i]; | 234 | av_video_mute.mute[i].avport = port[i]; |
235 | av_video_mute.mute[i].mute = mute; | 235 | av_video_mute.mute[i].mute = mute; |
236 | } | 236 | } |
237 | 237 | ||
238 | send_len = sizeof(av_video_mute.send_hdr) + | 238 | send_len = sizeof(av_video_mute.send_hdr) + |
239 | sizeof(struct ps3av_av_mute) * num_of_port; | 239 | sizeof(struct ps3av_av_mute) * num_of_port; |
240 | res = ps3av_do_pkt(PS3AV_CID_AV_VIDEO_MUTE, send_len, | 240 | res = ps3av_do_pkt(PS3AV_CID_AV_VIDEO_MUTE, send_len, |
241 | sizeof(av_video_mute), &av_video_mute.send_hdr); | 241 | sizeof(av_video_mute), &av_video_mute.send_hdr); |
242 | if (res < 0) | 242 | if (res < 0) |
243 | return res; | 243 | return res; |
244 | 244 | ||
245 | res = get_status(&av_video_mute); | 245 | res = get_status(&av_video_mute); |
246 | if (res) | 246 | if (res) |
247 | printk(KERN_ERR "PS3AV_CID_AV_VIDEO_MUTE: failed %x\n", res); | 247 | printk(KERN_ERR "PS3AV_CID_AV_VIDEO_MUTE: failed %x\n", res); |
248 | 248 | ||
249 | return res; | 249 | return res; |
250 | } | 250 | } |
251 | 251 | ||
252 | int ps3av_cmd_av_video_disable_sig(u32 port) | 252 | int ps3av_cmd_av_video_disable_sig(u32 port) |
253 | { | 253 | { |
254 | int res; | 254 | int res; |
255 | struct ps3av_pkt_av_video_disable_sig av_video_sig; | 255 | struct ps3av_pkt_av_video_disable_sig av_video_sig; |
256 | 256 | ||
257 | memset(&av_video_sig, 0, sizeof(av_video_sig)); | 257 | memset(&av_video_sig, 0, sizeof(av_video_sig)); |
258 | av_video_sig.avport = port; | 258 | av_video_sig.avport = port; |
259 | 259 | ||
260 | res = ps3av_do_pkt(PS3AV_CID_AV_VIDEO_DISABLE_SIG, | 260 | res = ps3av_do_pkt(PS3AV_CID_AV_VIDEO_DISABLE_SIG, |
261 | sizeof(av_video_sig), sizeof(av_video_sig), | 261 | sizeof(av_video_sig), sizeof(av_video_sig), |
262 | &av_video_sig.send_hdr); | 262 | &av_video_sig.send_hdr); |
263 | if (res < 0) | 263 | if (res < 0) |
264 | return res; | 264 | return res; |
265 | 265 | ||
266 | res = get_status(&av_video_sig); | 266 | res = get_status(&av_video_sig); |
267 | if (res) | 267 | if (res) |
268 | printk(KERN_ERR | 268 | printk(KERN_ERR |
269 | "PS3AV_CID_AV_VIDEO_DISABLE_SIG: failed %x port:%x\n", | 269 | "PS3AV_CID_AV_VIDEO_DISABLE_SIG: failed %x port:%x\n", |
270 | res, port); | 270 | res, port); |
271 | 271 | ||
272 | return res; | 272 | return res; |
273 | } | 273 | } |
274 | 274 | ||
275 | int ps3av_cmd_av_tv_mute(u32 avport, u32 mute) | 275 | int ps3av_cmd_av_tv_mute(u32 avport, u32 mute) |
276 | { | 276 | { |
277 | int res; | 277 | int res; |
278 | struct ps3av_pkt_av_tv_mute tv_mute; | 278 | struct ps3av_pkt_av_tv_mute tv_mute; |
279 | 279 | ||
280 | memset(&tv_mute, 0, sizeof(tv_mute)); | 280 | memset(&tv_mute, 0, sizeof(tv_mute)); |
281 | tv_mute.avport = avport; | 281 | tv_mute.avport = avport; |
282 | tv_mute.mute = mute; | 282 | tv_mute.mute = mute; |
283 | 283 | ||
284 | res = ps3av_do_pkt(PS3AV_CID_AV_TV_MUTE, sizeof(tv_mute), | 284 | res = ps3av_do_pkt(PS3AV_CID_AV_TV_MUTE, sizeof(tv_mute), |
285 | sizeof(tv_mute), &tv_mute.send_hdr); | 285 | sizeof(tv_mute), &tv_mute.send_hdr); |
286 | if (res < 0) | 286 | if (res < 0) |
287 | return res; | 287 | return res; |
288 | 288 | ||
289 | res = get_status(&tv_mute); | 289 | res = get_status(&tv_mute); |
290 | if (res) | 290 | if (res) |
291 | printk(KERN_ERR "PS3AV_CID_AV_TV_MUTE: failed %x port:%x\n", | 291 | printk(KERN_ERR "PS3AV_CID_AV_TV_MUTE: failed %x port:%x\n", |
292 | res, avport); | 292 | res, avport); |
293 | 293 | ||
294 | return res; | 294 | return res; |
295 | } | 295 | } |
296 | 296 | ||
297 | int ps3av_cmd_enable_event(void) | 297 | int ps3av_cmd_enable_event(void) |
298 | { | 298 | { |
299 | int res; | 299 | int res; |
300 | struct ps3av_pkt_av_event av_event; | 300 | struct ps3av_pkt_av_event av_event; |
301 | 301 | ||
302 | memset(&av_event, 0, sizeof(av_event)); | 302 | memset(&av_event, 0, sizeof(av_event)); |
303 | av_event.event_bit = PS3AV_CMD_EVENT_BIT_UNPLUGGED | | 303 | av_event.event_bit = PS3AV_CMD_EVENT_BIT_UNPLUGGED | |
304 | PS3AV_CMD_EVENT_BIT_PLUGGED | PS3AV_CMD_EVENT_BIT_HDCP_DONE; | 304 | PS3AV_CMD_EVENT_BIT_PLUGGED | PS3AV_CMD_EVENT_BIT_HDCP_DONE; |
305 | 305 | ||
306 | res = ps3av_do_pkt(PS3AV_CID_AV_ENABLE_EVENT, sizeof(av_event), | 306 | res = ps3av_do_pkt(PS3AV_CID_AV_ENABLE_EVENT, sizeof(av_event), |
307 | sizeof(av_event), &av_event.send_hdr); | 307 | sizeof(av_event), &av_event.send_hdr); |
308 | if (res < 0) | 308 | if (res < 0) |
309 | return res; | 309 | return res; |
310 | 310 | ||
311 | res = get_status(&av_event); | 311 | res = get_status(&av_event); |
312 | if (res) | 312 | if (res) |
313 | printk(KERN_ERR "PS3AV_CID_AV_ENABLE_EVENT: failed %x\n", res); | 313 | printk(KERN_ERR "PS3AV_CID_AV_ENABLE_EVENT: failed %x\n", res); |
314 | 314 | ||
315 | return res; | 315 | return res; |
316 | } | 316 | } |
317 | 317 | ||
318 | int ps3av_cmd_av_hdmi_mode(u8 mode) | 318 | int ps3av_cmd_av_hdmi_mode(u8 mode) |
319 | { | 319 | { |
320 | int res; | 320 | int res; |
321 | struct ps3av_pkt_av_hdmi_mode hdmi_mode; | 321 | struct ps3av_pkt_av_hdmi_mode hdmi_mode; |
322 | 322 | ||
323 | memset(&hdmi_mode, 0, sizeof(hdmi_mode)); | 323 | memset(&hdmi_mode, 0, sizeof(hdmi_mode)); |
324 | hdmi_mode.mode = mode; | 324 | hdmi_mode.mode = mode; |
325 | 325 | ||
326 | res = ps3av_do_pkt(PS3AV_CID_AV_HDMI_MODE, sizeof(hdmi_mode), | 326 | res = ps3av_do_pkt(PS3AV_CID_AV_HDMI_MODE, sizeof(hdmi_mode), |
327 | sizeof(hdmi_mode), &hdmi_mode.send_hdr); | 327 | sizeof(hdmi_mode), &hdmi_mode.send_hdr); |
328 | if (res < 0) | 328 | if (res < 0) |
329 | return res; | 329 | return res; |
330 | 330 | ||
331 | res = get_status(&hdmi_mode); | 331 | res = get_status(&hdmi_mode); |
332 | if (res && res != PS3AV_STATUS_UNSUPPORTED_HDMI_MODE) | 332 | if (res && res != PS3AV_STATUS_UNSUPPORTED_HDMI_MODE) |
333 | printk(KERN_ERR "PS3AV_CID_AV_HDMI_MODE: failed %x\n", res); | 333 | printk(KERN_ERR "PS3AV_CID_AV_HDMI_MODE: failed %x\n", res); |
334 | 334 | ||
335 | return res; | 335 | return res; |
336 | } | 336 | } |
337 | 337 | ||
338 | u32 ps3av_cmd_set_av_video_cs(void *p, u32 avport, int video_vid, int cs_out, | 338 | u32 ps3av_cmd_set_av_video_cs(void *p, u32 avport, int video_vid, int cs_out, |
339 | int aspect, u32 id) | 339 | int aspect, u32 id) |
340 | { | 340 | { |
341 | struct ps3av_pkt_av_video_cs *av_video_cs; | 341 | struct ps3av_pkt_av_video_cs *av_video_cs; |
342 | 342 | ||
343 | av_video_cs = (struct ps3av_pkt_av_video_cs *)p; | 343 | av_video_cs = (struct ps3av_pkt_av_video_cs *)p; |
344 | if (video_vid == -1) | 344 | if (video_vid == -1) |
345 | video_vid = PS3AV_CMD_VIDEO_VID_720P_60HZ; | 345 | video_vid = PS3AV_CMD_VIDEO_VID_720P_60HZ; |
346 | if (cs_out == -1) | 346 | if (cs_out == -1) |
347 | cs_out = PS3AV_CMD_VIDEO_CS_YUV444_8; | 347 | cs_out = PS3AV_CMD_VIDEO_CS_YUV444_8; |
348 | if (aspect == -1) | 348 | if (aspect == -1) |
349 | aspect = 0; | 349 | aspect = 0; |
350 | 350 | ||
351 | memset(av_video_cs, 0, sizeof(*av_video_cs)); | 351 | memset(av_video_cs, 0, sizeof(*av_video_cs)); |
352 | ps3av_set_hdr(PS3AV_CID_AV_VIDEO_CS, sizeof(*av_video_cs), | 352 | ps3av_set_hdr(PS3AV_CID_AV_VIDEO_CS, sizeof(*av_video_cs), |
353 | &av_video_cs->send_hdr); | 353 | &av_video_cs->send_hdr); |
354 | av_video_cs->avport = avport; | 354 | av_video_cs->avport = avport; |
355 | /* should be same as video_mode.resolution */ | 355 | /* should be same as video_mode.resolution */ |
356 | av_video_cs->av_vid = ps3av_vid_video2av(video_vid); | 356 | av_video_cs->av_vid = ps3av_vid_video2av(video_vid); |
357 | av_video_cs->av_cs_out = ps3av_cs_video2av(cs_out); | 357 | av_video_cs->av_cs_out = ps3av_cs_video2av(cs_out); |
358 | /* should be same as video_mode.video_cs_out */ | 358 | /* should be same as video_mode.video_cs_out */ |
359 | av_video_cs->av_cs_in = ps3av_cs_video2av(PS3AV_CMD_VIDEO_CS_RGB_8); | 359 | av_video_cs->av_cs_in = ps3av_cs_video2av(PS3AV_CMD_VIDEO_CS_RGB_8); |
360 | av_video_cs->bitlen_out = ps3av_cs_video2av_bitlen(cs_out); | 360 | av_video_cs->bitlen_out = ps3av_cs_video2av_bitlen(cs_out); |
361 | if ((id & PS3AV_MODE_WHITE) && ps3av_hdmi_range()) | 361 | if ((id & PS3AV_MODE_WHITE) && ps3av_hdmi_range()) |
362 | av_video_cs->super_white = PS3AV_CMD_AV_SUPER_WHITE_ON; | 362 | av_video_cs->super_white = PS3AV_CMD_AV_SUPER_WHITE_ON; |
363 | else /* default off */ | 363 | else /* default off */ |
364 | av_video_cs->super_white = PS3AV_CMD_AV_SUPER_WHITE_OFF; | 364 | av_video_cs->super_white = PS3AV_CMD_AV_SUPER_WHITE_OFF; |
365 | av_video_cs->aspect = aspect; | 365 | av_video_cs->aspect = aspect; |
366 | if (id & PS3AV_MODE_DITHER) { | 366 | if (id & PS3AV_MODE_DITHER) { |
367 | av_video_cs->dither = PS3AV_CMD_AV_DITHER_ON | 367 | av_video_cs->dither = PS3AV_CMD_AV_DITHER_ON |
368 | | PS3AV_CMD_AV_DITHER_8BIT; | 368 | | PS3AV_CMD_AV_DITHER_8BIT; |
369 | } else { | 369 | } else { |
370 | /* default off */ | 370 | /* default off */ |
371 | av_video_cs->dither = PS3AV_CMD_AV_DITHER_OFF; | 371 | av_video_cs->dither = PS3AV_CMD_AV_DITHER_OFF; |
372 | } | 372 | } |
373 | 373 | ||
374 | return sizeof(*av_video_cs); | 374 | return sizeof(*av_video_cs); |
375 | } | 375 | } |
376 | 376 | ||
377 | u32 ps3av_cmd_set_video_mode(void *p, u32 head, int video_vid, int video_fmt, | 377 | u32 ps3av_cmd_set_video_mode(void *p, u32 head, int video_vid, int video_fmt, |
378 | u32 id) | 378 | u32 id) |
379 | { | 379 | { |
380 | struct ps3av_pkt_video_mode *video_mode; | 380 | struct ps3av_pkt_video_mode *video_mode; |
381 | u32 x, y; | 381 | u32 x, y; |
382 | 382 | ||
383 | video_mode = (struct ps3av_pkt_video_mode *)p; | 383 | video_mode = (struct ps3av_pkt_video_mode *)p; |
384 | if (video_vid == -1) | 384 | if (video_vid == -1) |
385 | video_vid = PS3AV_CMD_VIDEO_VID_720P_60HZ; | 385 | video_vid = PS3AV_CMD_VIDEO_VID_720P_60HZ; |
386 | if (video_fmt == -1) | 386 | if (video_fmt == -1) |
387 | video_fmt = PS3AV_CMD_VIDEO_FMT_X8R8G8B8; | 387 | video_fmt = PS3AV_CMD_VIDEO_FMT_X8R8G8B8; |
388 | 388 | ||
389 | if (ps3av_video_mode2res(id, &x, &y)) | 389 | if (ps3av_video_mode2res(id, &x, &y)) |
390 | return 0; | 390 | return 0; |
391 | 391 | ||
392 | /* video mode */ | 392 | /* video mode */ |
393 | memset(video_mode, 0, sizeof(*video_mode)); | 393 | memset(video_mode, 0, sizeof(*video_mode)); |
394 | ps3av_set_hdr(PS3AV_CID_VIDEO_MODE, sizeof(*video_mode), | 394 | ps3av_set_hdr(PS3AV_CID_VIDEO_MODE, sizeof(*video_mode), |
395 | &video_mode->send_hdr); | 395 | &video_mode->send_hdr); |
396 | video_mode->video_head = head; | 396 | video_mode->video_head = head; |
397 | if (video_vid == PS3AV_CMD_VIDEO_VID_480I | 397 | if (video_vid == PS3AV_CMD_VIDEO_VID_480I |
398 | && head == PS3AV_CMD_VIDEO_HEAD_B) | 398 | && head == PS3AV_CMD_VIDEO_HEAD_B) |
399 | video_mode->video_vid = PS3AV_CMD_VIDEO_VID_480I_A; | 399 | video_mode->video_vid = PS3AV_CMD_VIDEO_VID_480I_A; |
400 | else | 400 | else |
401 | video_mode->video_vid = video_vid; | 401 | video_mode->video_vid = video_vid; |
402 | video_mode->width = (u16) x; | 402 | video_mode->width = (u16) x; |
403 | video_mode->height = (u16) y; | 403 | video_mode->height = (u16) y; |
404 | video_mode->pitch = video_mode->width * 4; /* line_length */ | 404 | video_mode->pitch = video_mode->width * 4; /* line_length */ |
405 | video_mode->video_out_format = PS3AV_CMD_VIDEO_OUT_FORMAT_RGB_12BIT; | 405 | video_mode->video_out_format = PS3AV_CMD_VIDEO_OUT_FORMAT_RGB_12BIT; |
406 | video_mode->video_format = ps3av_video_fmt_table[video_fmt].format; | 406 | video_mode->video_format = ps3av_video_fmt_table[video_fmt].format; |
407 | if ((id & PS3AV_MODE_COLOR) && ps3av_hdmi_range()) | 407 | if ((id & PS3AV_MODE_COLOR) && ps3av_hdmi_range()) |
408 | video_mode->video_cl_cnv = PS3AV_CMD_VIDEO_CL_CNV_DISABLE_LUT; | 408 | video_mode->video_cl_cnv = PS3AV_CMD_VIDEO_CL_CNV_DISABLE_LUT; |
409 | else /* default enable */ | 409 | else /* default enable */ |
410 | video_mode->video_cl_cnv = PS3AV_CMD_VIDEO_CL_CNV_ENABLE_LUT; | 410 | video_mode->video_cl_cnv = PS3AV_CMD_VIDEO_CL_CNV_ENABLE_LUT; |
411 | video_mode->video_order = ps3av_video_fmt_table[video_fmt].order; | 411 | video_mode->video_order = ps3av_video_fmt_table[video_fmt].order; |
412 | 412 | ||
413 | pr_debug("%s: video_mode:vid:%x width:%d height:%d pitch:%d out_format:%d format:%x order:%x\n", | 413 | pr_debug("%s: video_mode:vid:%x width:%d height:%d pitch:%d out_format:%d format:%x order:%x\n", |
414 | __func__, video_vid, video_mode->width, video_mode->height, | 414 | __func__, video_vid, video_mode->width, video_mode->height, |
415 | video_mode->pitch, video_mode->video_out_format, | 415 | video_mode->pitch, video_mode->video_out_format, |
416 | video_mode->video_format, video_mode->video_order); | 416 | video_mode->video_format, video_mode->video_order); |
417 | return sizeof(*video_mode); | 417 | return sizeof(*video_mode); |
418 | } | 418 | } |
419 | 419 | ||
420 | int ps3av_cmd_video_format_black(u32 head, u32 video_fmt, u32 mute) | 420 | int ps3av_cmd_video_format_black(u32 head, u32 video_fmt, u32 mute) |
421 | { | 421 | { |
422 | int res; | 422 | int res; |
423 | struct ps3av_pkt_video_format video_format; | 423 | struct ps3av_pkt_video_format video_format; |
424 | 424 | ||
425 | memset(&video_format, 0, sizeof(video_format)); | 425 | memset(&video_format, 0, sizeof(video_format)); |
426 | video_format.video_head = head; | 426 | video_format.video_head = head; |
427 | if (mute != PS3AV_CMD_MUTE_OFF) | 427 | if (mute != PS3AV_CMD_MUTE_OFF) |
428 | video_format.video_format = PS3AV_CMD_VIDEO_FORMAT_BLACK; | 428 | video_format.video_format = PS3AV_CMD_VIDEO_FORMAT_BLACK; |
429 | else | 429 | else |
430 | video_format.video_format = | 430 | video_format.video_format = |
431 | ps3av_video_fmt_table[video_fmt].format; | 431 | ps3av_video_fmt_table[video_fmt].format; |
432 | video_format.video_order = ps3av_video_fmt_table[video_fmt].order; | 432 | video_format.video_order = ps3av_video_fmt_table[video_fmt].order; |
433 | 433 | ||
434 | res = ps3av_do_pkt(PS3AV_CID_VIDEO_FORMAT, sizeof(video_format), | 434 | res = ps3av_do_pkt(PS3AV_CID_VIDEO_FORMAT, sizeof(video_format), |
435 | sizeof(video_format), &video_format.send_hdr); | 435 | sizeof(video_format), &video_format.send_hdr); |
436 | if (res < 0) | 436 | if (res < 0) |
437 | return res; | 437 | return res; |
438 | 438 | ||
439 | res = get_status(&video_format); | 439 | res = get_status(&video_format); |
440 | if (res) | 440 | if (res) |
441 | printk(KERN_ERR "PS3AV_CID_VIDEO_FORMAT: failed %x\n", res); | 441 | printk(KERN_ERR "PS3AV_CID_VIDEO_FORMAT: failed %x\n", res); |
442 | 442 | ||
443 | return res; | 443 | return res; |
444 | } | 444 | } |
445 | 445 | ||
446 | 446 | ||
447 | int ps3av_cmd_av_audio_mute(int num_of_port, u32 *port, u32 mute) | 447 | int ps3av_cmd_av_audio_mute(int num_of_port, u32 *port, u32 mute) |
448 | { | 448 | { |
449 | int i, res; | 449 | int i, res; |
450 | struct ps3av_pkt_av_audio_mute av_audio_mute; | 450 | struct ps3av_pkt_av_audio_mute av_audio_mute; |
451 | 451 | ||
452 | if (num_of_port > PS3AV_MUTE_PORT_MAX) | 452 | if (num_of_port > PS3AV_MUTE_PORT_MAX) |
453 | return -EINVAL; | 453 | return -EINVAL; |
454 | 454 | ||
455 | /* audio mute */ | 455 | /* audio mute */ |
456 | memset(&av_audio_mute, 0, sizeof(av_audio_mute)); | 456 | memset(&av_audio_mute, 0, sizeof(av_audio_mute)); |
457 | for (i = 0; i < num_of_port; i++) { | 457 | for (i = 0; i < num_of_port; i++) { |
458 | av_audio_mute.mute[i].avport = port[i]; | 458 | av_audio_mute.mute[i].avport = port[i]; |
459 | av_audio_mute.mute[i].mute = mute; | 459 | av_audio_mute.mute[i].mute = mute; |
460 | } | 460 | } |
461 | 461 | ||
462 | res = ps3av_do_pkt(PS3AV_CID_AV_AUDIO_MUTE, | 462 | res = ps3av_do_pkt(PS3AV_CID_AV_AUDIO_MUTE, |
463 | sizeof(av_audio_mute.send_hdr) + | 463 | sizeof(av_audio_mute.send_hdr) + |
464 | sizeof(struct ps3av_av_mute) * num_of_port, | 464 | sizeof(struct ps3av_av_mute) * num_of_port, |
465 | sizeof(av_audio_mute), &av_audio_mute.send_hdr); | 465 | sizeof(av_audio_mute), &av_audio_mute.send_hdr); |
466 | if (res < 0) | 466 | if (res < 0) |
467 | return res; | 467 | return res; |
468 | 468 | ||
469 | res = get_status(&av_audio_mute); | 469 | res = get_status(&av_audio_mute); |
470 | if (res) | 470 | if (res) |
471 | printk(KERN_ERR "PS3AV_CID_AV_AUDIO_MUTE: failed %x\n", res); | 471 | printk(KERN_ERR "PS3AV_CID_AV_AUDIO_MUTE: failed %x\n", res); |
472 | 472 | ||
473 | return res; | 473 | return res; |
474 | } | 474 | } |
475 | 475 | ||
476 | static const struct { | 476 | static const struct { |
477 | u32 fs; | 477 | u32 fs; |
478 | u8 mclk; | 478 | u8 mclk; |
479 | } ps3av_cnv_mclk_table[] = { | 479 | } ps3av_cnv_mclk_table[] = { |
480 | { PS3AV_CMD_AUDIO_FS_44K, PS3AV_CMD_AV_MCLK_512 }, | 480 | { PS3AV_CMD_AUDIO_FS_44K, PS3AV_CMD_AV_MCLK_512 }, |
481 | { PS3AV_CMD_AUDIO_FS_48K, PS3AV_CMD_AV_MCLK_512 }, | 481 | { PS3AV_CMD_AUDIO_FS_48K, PS3AV_CMD_AV_MCLK_512 }, |
482 | { PS3AV_CMD_AUDIO_FS_88K, PS3AV_CMD_AV_MCLK_256 }, | 482 | { PS3AV_CMD_AUDIO_FS_88K, PS3AV_CMD_AV_MCLK_256 }, |
483 | { PS3AV_CMD_AUDIO_FS_96K, PS3AV_CMD_AV_MCLK_256 }, | 483 | { PS3AV_CMD_AUDIO_FS_96K, PS3AV_CMD_AV_MCLK_256 }, |
484 | { PS3AV_CMD_AUDIO_FS_176K, PS3AV_CMD_AV_MCLK_128 }, | 484 | { PS3AV_CMD_AUDIO_FS_176K, PS3AV_CMD_AV_MCLK_128 }, |
485 | { PS3AV_CMD_AUDIO_FS_192K, PS3AV_CMD_AV_MCLK_128 } | 485 | { PS3AV_CMD_AUDIO_FS_192K, PS3AV_CMD_AV_MCLK_128 } |
486 | }; | 486 | }; |
487 | 487 | ||
488 | static u8 ps3av_cnv_mclk(u32 fs) | 488 | static u8 ps3av_cnv_mclk(u32 fs) |
489 | { | 489 | { |
490 | unsigned int i; | 490 | unsigned int i; |
491 | 491 | ||
492 | for (i = 0; i < ARRAY_SIZE(ps3av_cnv_mclk_table); i++) | 492 | for (i = 0; i < ARRAY_SIZE(ps3av_cnv_mclk_table); i++) |
493 | if (ps3av_cnv_mclk_table[i].fs == fs) | 493 | if (ps3av_cnv_mclk_table[i].fs == fs) |
494 | return ps3av_cnv_mclk_table[i].mclk; | 494 | return ps3av_cnv_mclk_table[i].mclk; |
495 | 495 | ||
496 | printk(KERN_ERR "%s failed, fs:%x\n", __func__, fs); | 496 | printk(KERN_ERR "%s failed, fs:%x\n", __func__, fs); |
497 | return 0; | 497 | return 0; |
498 | } | 498 | } |
499 | 499 | ||
500 | #define BASE PS3AV_CMD_AUDIO_FS_44K | 500 | #define BASE PS3AV_CMD_AUDIO_FS_44K |
501 | 501 | ||
502 | static const u32 ps3av_ns_table[][5] = { | 502 | static const u32 ps3av_ns_table[][5] = { |
503 | /* D1, D2, D3, D4, D5 */ | 503 | /* D1, D2, D3, D4, D5 */ |
504 | [PS3AV_CMD_AUDIO_FS_44K-BASE] = { 6272, 6272, 17836, 17836, 8918 }, | 504 | [PS3AV_CMD_AUDIO_FS_44K-BASE] = { 6272, 6272, 17836, 17836, 8918 }, |
505 | [PS3AV_CMD_AUDIO_FS_48K-BASE] = { 6144, 6144, 11648, 11648, 5824 }, | 505 | [PS3AV_CMD_AUDIO_FS_48K-BASE] = { 6144, 6144, 11648, 11648, 5824 }, |
506 | [PS3AV_CMD_AUDIO_FS_88K-BASE] = { 12544, 12544, 35672, 35672, 17836 }, | 506 | [PS3AV_CMD_AUDIO_FS_88K-BASE] = { 12544, 12544, 35672, 35672, 17836 }, |
507 | [PS3AV_CMD_AUDIO_FS_96K-BASE] = { 12288, 12288, 23296, 23296, 11648 }, | 507 | [PS3AV_CMD_AUDIO_FS_96K-BASE] = { 12288, 12288, 23296, 23296, 11648 }, |
508 | [PS3AV_CMD_AUDIO_FS_176K-BASE] = { 25088, 25088, 71344, 71344, 35672 }, | 508 | [PS3AV_CMD_AUDIO_FS_176K-BASE] = { 25088, 25088, 71344, 71344, 35672 }, |
509 | [PS3AV_CMD_AUDIO_FS_192K-BASE] = { 24576, 24576, 46592, 46592, 23296 } | 509 | [PS3AV_CMD_AUDIO_FS_192K-BASE] = { 24576, 24576, 46592, 46592, 23296 } |
510 | }; | 510 | }; |
511 | 511 | ||
512 | static void ps3av_cnv_ns(u8 *ns, u32 fs, u32 video_vid) | 512 | static void ps3av_cnv_ns(u8 *ns, u32 fs, u32 video_vid) |
513 | { | 513 | { |
514 | u32 av_vid, ns_val; | 514 | u32 av_vid, ns_val; |
515 | int d; | 515 | int d; |
516 | 516 | ||
517 | d = ns_val = 0; | 517 | d = ns_val = 0; |
518 | av_vid = ps3av_vid_video2av(video_vid); | 518 | av_vid = ps3av_vid_video2av(video_vid); |
519 | switch (av_vid) { | 519 | switch (av_vid) { |
520 | case PS3AV_CMD_AV_VID_480I: | 520 | case PS3AV_CMD_AV_VID_480I: |
521 | case PS3AV_CMD_AV_VID_576I: | 521 | case PS3AV_CMD_AV_VID_576I: |
522 | d = 0; | 522 | d = 0; |
523 | break; | 523 | break; |
524 | case PS3AV_CMD_AV_VID_480P: | 524 | case PS3AV_CMD_AV_VID_480P: |
525 | case PS3AV_CMD_AV_VID_576P: | 525 | case PS3AV_CMD_AV_VID_576P: |
526 | d = 1; | 526 | d = 1; |
527 | break; | 527 | break; |
528 | case PS3AV_CMD_AV_VID_1080I_60HZ: | 528 | case PS3AV_CMD_AV_VID_1080I_60HZ: |
529 | case PS3AV_CMD_AV_VID_1080I_50HZ: | 529 | case PS3AV_CMD_AV_VID_1080I_50HZ: |
530 | d = 2; | 530 | d = 2; |
531 | break; | 531 | break; |
532 | case PS3AV_CMD_AV_VID_720P_60HZ: | 532 | case PS3AV_CMD_AV_VID_720P_60HZ: |
533 | case PS3AV_CMD_AV_VID_720P_50HZ: | 533 | case PS3AV_CMD_AV_VID_720P_50HZ: |
534 | d = 3; | 534 | d = 3; |
535 | break; | 535 | break; |
536 | case PS3AV_CMD_AV_VID_1080P_60HZ: | 536 | case PS3AV_CMD_AV_VID_1080P_60HZ: |
537 | case PS3AV_CMD_AV_VID_1080P_50HZ: | 537 | case PS3AV_CMD_AV_VID_1080P_50HZ: |
538 | case PS3AV_CMD_AV_VID_WXGA: | 538 | case PS3AV_CMD_AV_VID_WXGA: |
539 | case PS3AV_CMD_AV_VID_SXGA: | 539 | case PS3AV_CMD_AV_VID_SXGA: |
540 | case PS3AV_CMD_AV_VID_WUXGA: | 540 | case PS3AV_CMD_AV_VID_WUXGA: |
541 | d = 4; | 541 | d = 4; |
542 | break; | 542 | break; |
543 | default: | 543 | default: |
544 | printk(KERN_ERR "%s failed, vid:%x\n", __func__, video_vid); | 544 | printk(KERN_ERR "%s failed, vid:%x\n", __func__, video_vid); |
545 | break; | 545 | break; |
546 | } | 546 | } |
547 | 547 | ||
548 | if (fs < PS3AV_CMD_AUDIO_FS_44K || fs > PS3AV_CMD_AUDIO_FS_192K) | 548 | if (fs < PS3AV_CMD_AUDIO_FS_44K || fs > PS3AV_CMD_AUDIO_FS_192K) |
549 | printk(KERN_ERR "%s failed, fs:%x\n", __func__, fs); | 549 | printk(KERN_ERR "%s failed, fs:%x\n", __func__, fs); |
550 | else | 550 | else |
551 | ns_val = ps3av_ns_table[PS3AV_CMD_AUDIO_FS_44K-BASE][d]; | 551 | ns_val = ps3av_ns_table[PS3AV_CMD_AUDIO_FS_44K-BASE][d]; |
552 | 552 | ||
553 | *ns++ = ns_val & 0x000000FF; | 553 | *ns++ = ns_val & 0x000000FF; |
554 | *ns++ = (ns_val & 0x0000FF00) >> 8; | 554 | *ns++ = (ns_val & 0x0000FF00) >> 8; |
555 | *ns = (ns_val & 0x00FF0000) >> 16; | 555 | *ns = (ns_val & 0x00FF0000) >> 16; |
556 | } | 556 | } |
557 | 557 | ||
558 | #undef BASE | 558 | #undef BASE |
559 | 559 | ||
560 | static u8 ps3av_cnv_enable(u32 source, const u8 *enable) | 560 | static u8 ps3av_cnv_enable(u32 source, const u8 *enable) |
561 | { | 561 | { |
562 | u8 ret = 0; | 562 | u8 ret = 0; |
563 | 563 | ||
564 | if (source == PS3AV_CMD_AUDIO_SOURCE_SPDIF) { | 564 | if (source == PS3AV_CMD_AUDIO_SOURCE_SPDIF) { |
565 | ret = 0x03; | 565 | ret = 0x03; |
566 | } else if (source == PS3AV_CMD_AUDIO_SOURCE_SERIAL) { | 566 | } else if (source == PS3AV_CMD_AUDIO_SOURCE_SERIAL) { |
567 | ret = ((enable[0] << 4) + (enable[1] << 5) + (enable[2] << 6) + | 567 | ret = ((enable[0] << 4) + (enable[1] << 5) + (enable[2] << 6) + |
568 | (enable[3] << 7)) | 0x01; | 568 | (enable[3] << 7)) | 0x01; |
569 | } else | 569 | } else |
570 | printk(KERN_ERR "%s failed, source:%x\n", __func__, source); | 570 | printk(KERN_ERR "%s failed, source:%x\n", __func__, source); |
571 | return ret; | 571 | return ret; |
572 | } | 572 | } |
573 | 573 | ||
574 | static u8 ps3av_cnv_fifomap(const u8 *map) | 574 | static u8 ps3av_cnv_fifomap(const u8 *map) |
575 | { | 575 | { |
576 | u8 ret = 0; | 576 | u8 ret = 0; |
577 | 577 | ||
578 | ret = map[0] + (map[1] << 2) + (map[2] << 4) + (map[3] << 6); | 578 | ret = map[0] + (map[1] << 2) + (map[2] << 4) + (map[3] << 6); |
579 | return ret; | 579 | return ret; |
580 | } | 580 | } |
581 | 581 | ||
582 | static u8 ps3av_cnv_inputlen(u32 word_bits) | 582 | static u8 ps3av_cnv_inputlen(u32 word_bits) |
583 | { | 583 | { |
584 | u8 ret = 0; | 584 | u8 ret = 0; |
585 | 585 | ||
586 | switch (word_bits) { | 586 | switch (word_bits) { |
587 | case PS3AV_CMD_AUDIO_WORD_BITS_16: | 587 | case PS3AV_CMD_AUDIO_WORD_BITS_16: |
588 | ret = PS3AV_CMD_AV_INPUTLEN_16; | 588 | ret = PS3AV_CMD_AV_INPUTLEN_16; |
589 | break; | 589 | break; |
590 | case PS3AV_CMD_AUDIO_WORD_BITS_20: | 590 | case PS3AV_CMD_AUDIO_WORD_BITS_20: |
591 | ret = PS3AV_CMD_AV_INPUTLEN_20; | 591 | ret = PS3AV_CMD_AV_INPUTLEN_20; |
592 | break; | 592 | break; |
593 | case PS3AV_CMD_AUDIO_WORD_BITS_24: | 593 | case PS3AV_CMD_AUDIO_WORD_BITS_24: |
594 | ret = PS3AV_CMD_AV_INPUTLEN_24; | 594 | ret = PS3AV_CMD_AV_INPUTLEN_24; |
595 | break; | 595 | break; |
596 | default: | 596 | default: |
597 | printk(KERN_ERR "%s failed, word_bits:%x\n", __func__, | 597 | printk(KERN_ERR "%s failed, word_bits:%x\n", __func__, |
598 | word_bits); | 598 | word_bits); |
599 | break; | 599 | break; |
600 | } | 600 | } |
601 | return ret; | 601 | return ret; |
602 | } | 602 | } |
603 | 603 | ||
604 | static u8 ps3av_cnv_layout(u32 num_of_ch) | 604 | static u8 ps3av_cnv_layout(u32 num_of_ch) |
605 | { | 605 | { |
606 | if (num_of_ch > PS3AV_CMD_AUDIO_NUM_OF_CH_8) { | 606 | if (num_of_ch > PS3AV_CMD_AUDIO_NUM_OF_CH_8) { |
607 | printk(KERN_ERR "%s failed, num_of_ch:%x\n", __func__, | 607 | printk(KERN_ERR "%s failed, num_of_ch:%x\n", __func__, |
608 | num_of_ch); | 608 | num_of_ch); |
609 | return 0; | 609 | return 0; |
610 | } | 610 | } |
611 | 611 | ||
612 | return num_of_ch == PS3AV_CMD_AUDIO_NUM_OF_CH_2 ? 0x0 : 0x1; | 612 | return num_of_ch == PS3AV_CMD_AUDIO_NUM_OF_CH_2 ? 0x0 : 0x1; |
613 | } | 613 | } |
614 | 614 | ||
615 | static void ps3av_cnv_info(struct ps3av_audio_info_frame *info, | 615 | static void ps3av_cnv_info(struct ps3av_audio_info_frame *info, |
616 | const struct ps3av_pkt_audio_mode *mode) | 616 | const struct ps3av_pkt_audio_mode *mode) |
617 | { | 617 | { |
618 | info->pb1.cc = mode->audio_num_of_ch + 1; /* CH2:0x01 --- CH8:0x07 */ | 618 | info->pb1.cc = mode->audio_num_of_ch + 1; /* CH2:0x01 --- CH8:0x07 */ |
619 | info->pb1.ct = 0; | 619 | info->pb1.ct = 0; |
620 | info->pb2.sf = 0; | 620 | info->pb2.sf = 0; |
621 | info->pb2.ss = 0; | 621 | info->pb2.ss = 0; |
622 | 622 | ||
623 | info->pb3 = 0; /* check mode->audio_format ?? */ | 623 | info->pb3 = 0; /* check mode->audio_format ?? */ |
624 | info->pb4 = mode->audio_layout; | 624 | info->pb4 = mode->audio_layout; |
625 | info->pb5.dm = mode->audio_downmix; | 625 | info->pb5.dm = mode->audio_downmix; |
626 | info->pb5.lsv = mode->audio_downmix_level; | 626 | info->pb5.lsv = mode->audio_downmix_level; |
627 | } | 627 | } |
628 | 628 | ||
629 | static void ps3av_cnv_chstat(u8 *chstat, const u8 *cs_info) | 629 | static void ps3av_cnv_chstat(u8 *chstat, const u8 *cs_info) |
630 | { | 630 | { |
631 | memcpy(chstat, cs_info, 5); | 631 | memcpy(chstat, cs_info, 5); |
632 | } | 632 | } |
633 | 633 | ||
634 | u32 ps3av_cmd_set_av_audio_param(void *p, u32 port, | 634 | u32 ps3av_cmd_set_av_audio_param(void *p, u32 port, |
635 | const struct ps3av_pkt_audio_mode *audio_mode, | 635 | const struct ps3av_pkt_audio_mode *audio_mode, |
636 | u32 video_vid) | 636 | u32 video_vid) |
637 | { | 637 | { |
638 | struct ps3av_pkt_av_audio_param *param; | 638 | struct ps3av_pkt_av_audio_param *param; |
639 | 639 | ||
640 | param = (struct ps3av_pkt_av_audio_param *)p; | 640 | param = (struct ps3av_pkt_av_audio_param *)p; |
641 | 641 | ||
642 | memset(param, 0, sizeof(*param)); | 642 | memset(param, 0, sizeof(*param)); |
643 | ps3av_set_hdr(PS3AV_CID_AV_AUDIO_PARAM, sizeof(*param), | 643 | ps3av_set_hdr(PS3AV_CID_AV_AUDIO_PARAM, sizeof(*param), |
644 | ¶m->send_hdr); | 644 | ¶m->send_hdr); |
645 | 645 | ||
646 | param->avport = port; | 646 | param->avport = port; |
647 | param->mclk = ps3av_cnv_mclk(audio_mode->audio_fs) | 0x80; | 647 | param->mclk = ps3av_cnv_mclk(audio_mode->audio_fs) | 0x80; |
648 | ps3av_cnv_ns(param->ns, audio_mode->audio_fs, video_vid); | 648 | ps3av_cnv_ns(param->ns, audio_mode->audio_fs, video_vid); |
649 | param->enable = ps3av_cnv_enable(audio_mode->audio_source, | 649 | param->enable = ps3av_cnv_enable(audio_mode->audio_source, |
650 | audio_mode->audio_enable); | 650 | audio_mode->audio_enable); |
651 | param->swaplr = 0x09; | 651 | param->swaplr = 0x09; |
652 | param->fifomap = ps3av_cnv_fifomap(audio_mode->audio_map); | 652 | param->fifomap = ps3av_cnv_fifomap(audio_mode->audio_map); |
653 | param->inputctrl = 0x49; | 653 | param->inputctrl = 0x49; |
654 | param->inputlen = ps3av_cnv_inputlen(audio_mode->audio_word_bits); | 654 | param->inputlen = ps3av_cnv_inputlen(audio_mode->audio_word_bits); |
655 | param->layout = ps3av_cnv_layout(audio_mode->audio_num_of_ch); | 655 | param->layout = ps3av_cnv_layout(audio_mode->audio_num_of_ch); |
656 | ps3av_cnv_info(¶m->info, audio_mode); | 656 | ps3av_cnv_info(¶m->info, audio_mode); |
657 | ps3av_cnv_chstat(param->chstat, audio_mode->audio_cs_info); | 657 | ps3av_cnv_chstat(param->chstat, audio_mode->audio_cs_info); |
658 | 658 | ||
659 | return sizeof(*param); | 659 | return sizeof(*param); |
660 | } | 660 | } |
661 | 661 | ||
662 | /* default cs val */ | 662 | /* default cs val */ |
663 | u8 ps3av_mode_cs_info[] = { | 663 | u8 ps3av_mode_cs_info[] = { |
664 | 0x00, 0x09, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00 | 664 | 0x00, 0x09, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00 |
665 | }; | 665 | }; |
666 | EXPORT_SYMBOL_GPL(ps3av_mode_cs_info); | 666 | EXPORT_SYMBOL_GPL(ps3av_mode_cs_info); |
667 | 667 | ||
668 | #define CS_44 0x00 | 668 | #define CS_44 0x00 |
669 | #define CS_48 0x02 | 669 | #define CS_48 0x02 |
670 | #define CS_88 0x08 | 670 | #define CS_88 0x08 |
671 | #define CS_96 0x0a | 671 | #define CS_96 0x0a |
672 | #define CS_176 0x0c | 672 | #define CS_176 0x0c |
673 | #define CS_192 0x0e | 673 | #define CS_192 0x0e |
674 | #define CS_MASK 0x0f | 674 | #define CS_MASK 0x0f |
675 | #define CS_BIT 0x40 | 675 | #define CS_BIT 0x40 |
676 | 676 | ||
677 | void ps3av_cmd_set_audio_mode(struct ps3av_pkt_audio_mode *audio, u32 avport, | 677 | void ps3av_cmd_set_audio_mode(struct ps3av_pkt_audio_mode *audio, u32 avport, |
678 | u32 ch, u32 fs, u32 word_bits, u32 format, | 678 | u32 ch, u32 fs, u32 word_bits, u32 format, |
679 | u32 source) | 679 | u32 source) |
680 | { | 680 | { |
681 | int spdif_through; | 681 | int spdif_through; |
682 | int i; | 682 | int i; |
683 | 683 | ||
684 | if (!(ch | fs | format | word_bits | source)) { | 684 | if (!(ch | fs | format | word_bits | source)) { |
685 | ch = PS3AV_CMD_AUDIO_NUM_OF_CH_2; | 685 | ch = PS3AV_CMD_AUDIO_NUM_OF_CH_2; |
686 | fs = PS3AV_CMD_AUDIO_FS_48K; | 686 | fs = PS3AV_CMD_AUDIO_FS_48K; |
687 | word_bits = PS3AV_CMD_AUDIO_WORD_BITS_16; | 687 | word_bits = PS3AV_CMD_AUDIO_WORD_BITS_16; |
688 | format = PS3AV_CMD_AUDIO_FORMAT_PCM; | 688 | format = PS3AV_CMD_AUDIO_FORMAT_PCM; |
689 | source = PS3AV_CMD_AUDIO_SOURCE_SERIAL; | 689 | source = PS3AV_CMD_AUDIO_SOURCE_SERIAL; |
690 | } | 690 | } |
691 | 691 | ||
692 | /* audio mode */ | 692 | /* audio mode */ |
693 | memset(audio, 0, sizeof(*audio)); | 693 | memset(audio, 0, sizeof(*audio)); |
694 | ps3av_set_hdr(PS3AV_CID_AUDIO_MODE, sizeof(*audio), &audio->send_hdr); | 694 | ps3av_set_hdr(PS3AV_CID_AUDIO_MODE, sizeof(*audio), &audio->send_hdr); |
695 | 695 | ||
696 | audio->avport = (u8) avport; | 696 | audio->avport = (u8) avport; |
697 | audio->mask = 0x0FFF; /* XXX set all */ | 697 | audio->mask = 0x0FFF; /* XXX set all */ |
698 | audio->audio_num_of_ch = ch; | 698 | audio->audio_num_of_ch = ch; |
699 | audio->audio_fs = fs; | 699 | audio->audio_fs = fs; |
700 | audio->audio_word_bits = word_bits; | 700 | audio->audio_word_bits = word_bits; |
701 | audio->audio_format = format; | 701 | audio->audio_format = format; |
702 | audio->audio_source = source; | 702 | audio->audio_source = source; |
703 | 703 | ||
704 | switch (ch) { | 704 | switch (ch) { |
705 | case PS3AV_CMD_AUDIO_NUM_OF_CH_8: | 705 | case PS3AV_CMD_AUDIO_NUM_OF_CH_8: |
706 | audio->audio_enable[3] = 1; | 706 | audio->audio_enable[3] = 1; |
707 | /* fall through */ | 707 | /* fall through */ |
708 | case PS3AV_CMD_AUDIO_NUM_OF_CH_6: | 708 | case PS3AV_CMD_AUDIO_NUM_OF_CH_6: |
709 | audio->audio_enable[2] = 1; | 709 | audio->audio_enable[2] = 1; |
710 | audio->audio_enable[1] = 1; | 710 | audio->audio_enable[1] = 1; |
711 | /* fall through */ | 711 | /* fall through */ |
712 | case PS3AV_CMD_AUDIO_NUM_OF_CH_2: | 712 | case PS3AV_CMD_AUDIO_NUM_OF_CH_2: |
713 | default: | 713 | default: |
714 | audio->audio_enable[0] = 1; | 714 | audio->audio_enable[0] = 1; |
715 | } | 715 | } |
716 | 716 | ||
717 | /* audio swap L/R */ | 717 | /* audio swap L/R */ |
718 | for (i = 0; i < 4; i++) | 718 | for (i = 0; i < 4; i++) |
719 | audio->audio_swap[i] = PS3AV_CMD_AUDIO_SWAP_0; /* no swap */ | 719 | audio->audio_swap[i] = PS3AV_CMD_AUDIO_SWAP_0; /* no swap */ |
720 | 720 | ||
721 | /* audio serial input mapping */ | 721 | /* audio serial input mapping */ |
722 | audio->audio_map[0] = PS3AV_CMD_AUDIO_MAP_OUTPUT_0; | 722 | audio->audio_map[0] = PS3AV_CMD_AUDIO_MAP_OUTPUT_0; |
723 | audio->audio_map[1] = PS3AV_CMD_AUDIO_MAP_OUTPUT_1; | 723 | audio->audio_map[1] = PS3AV_CMD_AUDIO_MAP_OUTPUT_1; |
724 | audio->audio_map[2] = PS3AV_CMD_AUDIO_MAP_OUTPUT_2; | 724 | audio->audio_map[2] = PS3AV_CMD_AUDIO_MAP_OUTPUT_2; |
725 | audio->audio_map[3] = PS3AV_CMD_AUDIO_MAP_OUTPUT_3; | 725 | audio->audio_map[3] = PS3AV_CMD_AUDIO_MAP_OUTPUT_3; |
726 | 726 | ||
727 | /* audio speaker layout */ | 727 | /* audio speaker layout */ |
728 | if (avport == PS3AV_CMD_AVPORT_HDMI_0 || | 728 | if (avport == PS3AV_CMD_AVPORT_HDMI_0 || |
729 | avport == PS3AV_CMD_AVPORT_HDMI_1) { | 729 | avport == PS3AV_CMD_AVPORT_HDMI_1) { |
730 | switch (ch) { | 730 | switch (ch) { |
731 | case PS3AV_CMD_AUDIO_NUM_OF_CH_8: | 731 | case PS3AV_CMD_AUDIO_NUM_OF_CH_8: |
732 | audio->audio_layout = PS3AV_CMD_AUDIO_LAYOUT_8CH; | 732 | audio->audio_layout = PS3AV_CMD_AUDIO_LAYOUT_8CH; |
733 | break; | 733 | break; |
734 | case PS3AV_CMD_AUDIO_NUM_OF_CH_6: | 734 | case PS3AV_CMD_AUDIO_NUM_OF_CH_6: |
735 | audio->audio_layout = PS3AV_CMD_AUDIO_LAYOUT_6CH; | 735 | audio->audio_layout = PS3AV_CMD_AUDIO_LAYOUT_6CH; |
736 | break; | 736 | break; |
737 | case PS3AV_CMD_AUDIO_NUM_OF_CH_2: | 737 | case PS3AV_CMD_AUDIO_NUM_OF_CH_2: |
738 | default: | 738 | default: |
739 | audio->audio_layout = PS3AV_CMD_AUDIO_LAYOUT_2CH; | 739 | audio->audio_layout = PS3AV_CMD_AUDIO_LAYOUT_2CH; |
740 | break; | 740 | break; |
741 | } | 741 | } |
742 | } else { | 742 | } else { |
743 | audio->audio_layout = PS3AV_CMD_AUDIO_LAYOUT_2CH; | 743 | audio->audio_layout = PS3AV_CMD_AUDIO_LAYOUT_2CH; |
744 | } | 744 | } |
745 | 745 | ||
746 | /* audio downmix permission */ | 746 | /* audio downmix permission */ |
747 | audio->audio_downmix = PS3AV_CMD_AUDIO_DOWNMIX_PERMITTED; | 747 | audio->audio_downmix = PS3AV_CMD_AUDIO_DOWNMIX_PERMITTED; |
748 | /* audio downmix level shift (0:0dB to 15:15dB) */ | 748 | /* audio downmix level shift (0:0dB to 15:15dB) */ |
749 | audio->audio_downmix_level = 0; /* 0dB */ | 749 | audio->audio_downmix_level = 0; /* 0dB */ |
750 | 750 | ||
751 | /* set ch status */ | 751 | /* set ch status */ |
752 | for (i = 0; i < 8; i++) | 752 | for (i = 0; i < 8; i++) |
753 | audio->audio_cs_info[i] = ps3av_mode_cs_info[i]; | 753 | audio->audio_cs_info[i] = ps3av_mode_cs_info[i]; |
754 | 754 | ||
755 | switch (fs) { | 755 | switch (fs) { |
756 | case PS3AV_CMD_AUDIO_FS_44K: | 756 | case PS3AV_CMD_AUDIO_FS_44K: |
757 | audio->audio_cs_info[3] &= ~CS_MASK; | 757 | audio->audio_cs_info[3] &= ~CS_MASK; |
758 | audio->audio_cs_info[3] |= CS_44; | 758 | audio->audio_cs_info[3] |= CS_44; |
759 | break; | 759 | break; |
760 | case PS3AV_CMD_AUDIO_FS_88K: | 760 | case PS3AV_CMD_AUDIO_FS_88K: |
761 | audio->audio_cs_info[3] &= ~CS_MASK; | 761 | audio->audio_cs_info[3] &= ~CS_MASK; |
762 | audio->audio_cs_info[3] |= CS_88; | 762 | audio->audio_cs_info[3] |= CS_88; |
763 | break; | 763 | break; |
764 | case PS3AV_CMD_AUDIO_FS_96K: | 764 | case PS3AV_CMD_AUDIO_FS_96K: |
765 | audio->audio_cs_info[3] &= ~CS_MASK; | 765 | audio->audio_cs_info[3] &= ~CS_MASK; |
766 | audio->audio_cs_info[3] |= CS_96; | 766 | audio->audio_cs_info[3] |= CS_96; |
767 | break; | 767 | break; |
768 | case PS3AV_CMD_AUDIO_FS_176K: | 768 | case PS3AV_CMD_AUDIO_FS_176K: |
769 | audio->audio_cs_info[3] &= ~CS_MASK; | 769 | audio->audio_cs_info[3] &= ~CS_MASK; |
770 | audio->audio_cs_info[3] |= CS_176; | 770 | audio->audio_cs_info[3] |= CS_176; |
771 | break; | 771 | break; |
772 | case PS3AV_CMD_AUDIO_FS_192K: | 772 | case PS3AV_CMD_AUDIO_FS_192K: |
773 | audio->audio_cs_info[3] &= ~CS_MASK; | 773 | audio->audio_cs_info[3] &= ~CS_MASK; |
774 | audio->audio_cs_info[3] |= CS_192; | 774 | audio->audio_cs_info[3] |= CS_192; |
775 | break; | 775 | break; |
776 | default: | 776 | default: |
777 | break; | 777 | break; |
778 | } | 778 | } |
779 | 779 | ||
780 | /* non-audio bit */ | 780 | /* non-audio bit */ |
781 | spdif_through = audio->audio_cs_info[0] & 0x02; | 781 | spdif_through = audio->audio_cs_info[0] & 0x02; |
782 | 782 | ||
783 | /* pass through setting */ | 783 | /* pass through setting */ |
784 | if (spdif_through && | 784 | if (spdif_through && |
785 | (avport == PS3AV_CMD_AVPORT_SPDIF_0 || | 785 | (avport == PS3AV_CMD_AVPORT_SPDIF_0 || |
786 | avport == PS3AV_CMD_AVPORT_SPDIF_1 || | 786 | avport == PS3AV_CMD_AVPORT_SPDIF_1 || |
787 | avport == PS3AV_CMD_AVPORT_HDMI_0 || | 787 | avport == PS3AV_CMD_AVPORT_HDMI_0 || |
788 | avport == PS3AV_CMD_AVPORT_HDMI_1)) { | 788 | avport == PS3AV_CMD_AVPORT_HDMI_1)) { |
789 | audio->audio_word_bits = PS3AV_CMD_AUDIO_WORD_BITS_16; | 789 | audio->audio_word_bits = PS3AV_CMD_AUDIO_WORD_BITS_16; |
790 | audio->audio_format = PS3AV_CMD_AUDIO_FORMAT_BITSTREAM; | 790 | audio->audio_format = PS3AV_CMD_AUDIO_FORMAT_BITSTREAM; |
791 | } | 791 | } |
792 | } | 792 | } |
793 | 793 | ||
794 | int ps3av_cmd_audio_mode(struct ps3av_pkt_audio_mode *audio_mode) | 794 | int ps3av_cmd_audio_mode(struct ps3av_pkt_audio_mode *audio_mode) |
795 | { | 795 | { |
796 | int res; | 796 | int res; |
797 | 797 | ||
798 | res = ps3av_do_pkt(PS3AV_CID_AUDIO_MODE, sizeof(*audio_mode), | 798 | res = ps3av_do_pkt(PS3AV_CID_AUDIO_MODE, sizeof(*audio_mode), |
799 | sizeof(*audio_mode), &audio_mode->send_hdr); | 799 | sizeof(*audio_mode), &audio_mode->send_hdr); |
800 | if (res < 0) | 800 | if (res < 0) |
801 | return res; | 801 | return res; |
802 | 802 | ||
803 | res = get_status(audio_mode); | 803 | res = get_status(audio_mode); |
804 | if (res) | 804 | if (res) |
805 | printk(KERN_ERR "PS3AV_CID_AUDIO_MODE: failed %x\n", res); | 805 | printk(KERN_ERR "PS3AV_CID_AUDIO_MODE: failed %x\n", res); |
806 | 806 | ||
807 | return res; | 807 | return res; |
808 | } | 808 | } |
809 | 809 | ||
810 | int ps3av_cmd_audio_mute(int num_of_port, u32 *port, u32 mute) | 810 | int ps3av_cmd_audio_mute(int num_of_port, u32 *port, u32 mute) |
811 | { | 811 | { |
812 | int i, res; | 812 | int i, res; |
813 | struct ps3av_pkt_audio_mute audio_mute; | 813 | struct ps3av_pkt_audio_mute audio_mute; |
814 | 814 | ||
815 | if (num_of_port > PS3AV_OPT_PORT_MAX) | 815 | if (num_of_port > PS3AV_OPT_PORT_MAX) |
816 | return -EINVAL; | 816 | return -EINVAL; |
817 | 817 | ||
818 | /* audio mute */ | 818 | /* audio mute */ |
819 | memset(&audio_mute, 0, sizeof(audio_mute)); | 819 | memset(&audio_mute, 0, sizeof(audio_mute)); |
820 | for (i = 0; i < num_of_port; i++) { | 820 | for (i = 0; i < num_of_port; i++) { |
821 | audio_mute.mute[i].avport = port[i]; | 821 | audio_mute.mute[i].avport = port[i]; |
822 | audio_mute.mute[i].mute = mute; | 822 | audio_mute.mute[i].mute = mute; |
823 | } | 823 | } |
824 | 824 | ||
825 | res = ps3av_do_pkt(PS3AV_CID_AUDIO_MUTE, | 825 | res = ps3av_do_pkt(PS3AV_CID_AUDIO_MUTE, |
826 | sizeof(audio_mute.send_hdr) + | 826 | sizeof(audio_mute.send_hdr) + |
827 | sizeof(struct ps3av_audio_mute) * num_of_port, | 827 | sizeof(struct ps3av_audio_mute) * num_of_port, |
828 | sizeof(audio_mute), &audio_mute.send_hdr); | 828 | sizeof(audio_mute), &audio_mute.send_hdr); |
829 | if (res < 0) | 829 | if (res < 0) |
830 | return res; | 830 | return res; |
831 | 831 | ||
832 | res = get_status(&audio_mute); | 832 | res = get_status(&audio_mute); |
833 | if (res) | 833 | if (res) |
834 | printk(KERN_ERR "PS3AV_CID_AUDIO_MUTE: failed %x\n", res); | 834 | printk(KERN_ERR "PS3AV_CID_AUDIO_MUTE: failed %x\n", res); |
835 | 835 | ||
836 | return res; | 836 | return res; |
837 | } | 837 | } |
838 | 838 | ||
839 | int ps3av_cmd_audio_active(int active, u32 port) | 839 | int ps3av_cmd_audio_active(int active, u32 port) |
840 | { | 840 | { |
841 | int res; | 841 | int res; |
842 | struct ps3av_pkt_audio_active audio_active; | 842 | struct ps3av_pkt_audio_active audio_active; |
843 | u32 cid; | 843 | u32 cid; |
844 | 844 | ||
845 | /* audio active */ | 845 | /* audio active */ |
846 | memset(&audio_active, 0, sizeof(audio_active)); | 846 | memset(&audio_active, 0, sizeof(audio_active)); |
847 | audio_active.audio_port = port; | 847 | audio_active.audio_port = port; |
848 | cid = active ? PS3AV_CID_AUDIO_ACTIVE : PS3AV_CID_AUDIO_INACTIVE; | 848 | cid = active ? PS3AV_CID_AUDIO_ACTIVE : PS3AV_CID_AUDIO_INACTIVE; |
849 | 849 | ||
850 | res = ps3av_do_pkt(cid, sizeof(audio_active), sizeof(audio_active), | 850 | res = ps3av_do_pkt(cid, sizeof(audio_active), sizeof(audio_active), |
851 | &audio_active.send_hdr); | 851 | &audio_active.send_hdr); |
852 | if (res < 0) | 852 | if (res < 0) |
853 | return res; | 853 | return res; |
854 | 854 | ||
855 | res = get_status(&audio_active); | 855 | res = get_status(&audio_active); |
856 | if (res) | 856 | if (res) |
857 | printk(KERN_ERR "PS3AV_CID_AUDIO_ACTIVE:%x failed %x\n", cid, | 857 | printk(KERN_ERR "PS3AV_CID_AUDIO_ACTIVE:%x failed %x\n", cid, |
858 | res); | 858 | res); |
859 | 859 | ||
860 | return res; | 860 | return res; |
861 | } | 861 | } |
862 | 862 | ||
863 | int ps3av_cmd_avb_param(struct ps3av_pkt_avb_param *avb, u32 send_len) | 863 | int ps3av_cmd_avb_param(struct ps3av_pkt_avb_param *avb, u32 send_len) |
864 | { | 864 | { |
865 | int res; | 865 | int res; |
866 | 866 | ||
867 | ps3av_flip_ctl(0); /* flip off */ | 867 | mutex_lock(&ps3_gpu_mutex); |
868 | 868 | ||
869 | /* avb packet */ | 869 | /* avb packet */ |
870 | res = ps3av_do_pkt(PS3AV_CID_AVB_PARAM, send_len, sizeof(*avb), | 870 | res = ps3av_do_pkt(PS3AV_CID_AVB_PARAM, send_len, sizeof(*avb), |
871 | &avb->send_hdr); | 871 | &avb->send_hdr); |
872 | if (res < 0) | 872 | if (res < 0) |
873 | goto out; | 873 | goto out; |
874 | 874 | ||
875 | res = get_status(avb); | 875 | res = get_status(avb); |
876 | if (res) | 876 | if (res) |
877 | pr_debug("%s: PS3AV_CID_AVB_PARAM: failed %x\n", __func__, | 877 | pr_debug("%s: PS3AV_CID_AVB_PARAM: failed %x\n", __func__, |
878 | res); | 878 | res); |
879 | 879 | ||
880 | out: | 880 | out: |
881 | ps3av_flip_ctl(1); /* flip on */ | 881 | mutex_unlock(&ps3_gpu_mutex); |
882 | return res; | 882 | return res; |
883 | } | 883 | } |
884 | 884 | ||
885 | int ps3av_cmd_av_get_hw_conf(struct ps3av_pkt_av_get_hw_conf *hw_conf) | 885 | int ps3av_cmd_av_get_hw_conf(struct ps3av_pkt_av_get_hw_conf *hw_conf) |
886 | { | 886 | { |
887 | int res; | 887 | int res; |
888 | 888 | ||
889 | memset(hw_conf, 0, sizeof(*hw_conf)); | 889 | memset(hw_conf, 0, sizeof(*hw_conf)); |
890 | 890 | ||
891 | res = ps3av_do_pkt(PS3AV_CID_AV_GET_HW_CONF, sizeof(hw_conf->send_hdr), | 891 | res = ps3av_do_pkt(PS3AV_CID_AV_GET_HW_CONF, sizeof(hw_conf->send_hdr), |
892 | sizeof(*hw_conf), &hw_conf->send_hdr); | 892 | sizeof(*hw_conf), &hw_conf->send_hdr); |
893 | if (res < 0) | 893 | if (res < 0) |
894 | return res; | 894 | return res; |
895 | 895 | ||
896 | res = get_status(hw_conf); | 896 | res = get_status(hw_conf); |
897 | if (res) | 897 | if (res) |
898 | printk(KERN_ERR "PS3AV_CID_AV_GET_HW_CONF: failed %x\n", res); | 898 | printk(KERN_ERR "PS3AV_CID_AV_GET_HW_CONF: failed %x\n", res); |
899 | 899 | ||
900 | return res; | 900 | return res; |
901 | } | 901 | } |
902 | 902 | ||
903 | int ps3av_cmd_video_get_monitor_info(struct ps3av_pkt_av_get_monitor_info *info, | 903 | int ps3av_cmd_video_get_monitor_info(struct ps3av_pkt_av_get_monitor_info *info, |
904 | u32 avport) | 904 | u32 avport) |
905 | { | 905 | { |
906 | int res; | 906 | int res; |
907 | 907 | ||
908 | memset(info, 0, sizeof(*info)); | 908 | memset(info, 0, sizeof(*info)); |
909 | info->avport = avport; | 909 | info->avport = avport; |
910 | 910 | ||
911 | res = ps3av_do_pkt(PS3AV_CID_AV_GET_MONITOR_INFO, | 911 | res = ps3av_do_pkt(PS3AV_CID_AV_GET_MONITOR_INFO, |
912 | sizeof(info->send_hdr) + sizeof(info->avport) + | 912 | sizeof(info->send_hdr) + sizeof(info->avport) + |
913 | sizeof(info->reserved), | 913 | sizeof(info->reserved), |
914 | sizeof(*info), &info->send_hdr); | 914 | sizeof(*info), &info->send_hdr); |
915 | if (res < 0) | 915 | if (res < 0) |
916 | return res; | 916 | return res; |
917 | 917 | ||
918 | res = get_status(info); | 918 | res = get_status(info); |
919 | if (res) | 919 | if (res) |
920 | printk(KERN_ERR "PS3AV_CID_AV_GET_MONITOR_INFO: failed %x\n", | 920 | printk(KERN_ERR "PS3AV_CID_AV_GET_MONITOR_INFO: failed %x\n", |
921 | res); | 921 | res); |
922 | 922 | ||
923 | return res; | 923 | return res; |
924 | } | 924 | } |
925 | 925 | ||
926 | #define PS3AV_AV_LAYOUT_0 (PS3AV_CMD_AV_LAYOUT_32 \ | 926 | #define PS3AV_AV_LAYOUT_0 (PS3AV_CMD_AV_LAYOUT_32 \ |
927 | | PS3AV_CMD_AV_LAYOUT_44 \ | 927 | | PS3AV_CMD_AV_LAYOUT_44 \ |
928 | | PS3AV_CMD_AV_LAYOUT_48) | 928 | | PS3AV_CMD_AV_LAYOUT_48) |
929 | 929 | ||
930 | #define PS3AV_AV_LAYOUT_1 (PS3AV_AV_LAYOUT_0 \ | 930 | #define PS3AV_AV_LAYOUT_1 (PS3AV_AV_LAYOUT_0 \ |
931 | | PS3AV_CMD_AV_LAYOUT_88 \ | 931 | | PS3AV_CMD_AV_LAYOUT_88 \ |
932 | | PS3AV_CMD_AV_LAYOUT_96 \ | 932 | | PS3AV_CMD_AV_LAYOUT_96 \ |
933 | | PS3AV_CMD_AV_LAYOUT_176 \ | 933 | | PS3AV_CMD_AV_LAYOUT_176 \ |
934 | | PS3AV_CMD_AV_LAYOUT_192) | 934 | | PS3AV_CMD_AV_LAYOUT_192) |
935 | 935 | ||
936 | 936 |
drivers/video/ps3fb.c
1 | /* | 1 | /* |
2 | * linux/drivers/video/ps3fb.c -- PS3 GPU frame buffer device | 2 | * linux/drivers/video/ps3fb.c -- PS3 GPU frame buffer device |
3 | * | 3 | * |
4 | * Copyright (C) 2006 Sony Computer Entertainment Inc. | 4 | * Copyright (C) 2006 Sony Computer Entertainment Inc. |
5 | * Copyright 2006, 2007 Sony Corporation | 5 | * Copyright 2006, 2007 Sony Corporation |
6 | * | 6 | * |
7 | * This file is based on : | 7 | * This file is based on : |
8 | * | 8 | * |
9 | * linux/drivers/video/vfb.c -- Virtual frame buffer device | 9 | * linux/drivers/video/vfb.c -- Virtual frame buffer device |
10 | * | 10 | * |
11 | * Copyright (C) 2002 James Simmons | 11 | * Copyright (C) 2002 James Simmons |
12 | * | 12 | * |
13 | * Copyright (C) 1997 Geert Uytterhoeven | 13 | * Copyright (C) 1997 Geert Uytterhoeven |
14 | * | 14 | * |
15 | * This file is subject to the terms and conditions of the GNU General Public | 15 | * This file is subject to the terms and conditions of the GNU General Public |
16 | * License. See the file COPYING in the main directory of this archive for | 16 | * License. See the file COPYING in the main directory of this archive for |
17 | * more details. | 17 | * more details. |
18 | */ | 18 | */ |
19 | 19 | ||
20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
21 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
22 | #include <linux/errno.h> | 22 | #include <linux/errno.h> |
23 | #include <linux/string.h> | 23 | #include <linux/string.h> |
24 | #include <linux/mm.h> | 24 | #include <linux/mm.h> |
25 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
26 | #include <linux/console.h> | 26 | #include <linux/console.h> |
27 | #include <linux/ioctl.h> | 27 | #include <linux/ioctl.h> |
28 | #include <linux/kthread.h> | 28 | #include <linux/kthread.h> |
29 | #include <linux/freezer.h> | 29 | #include <linux/freezer.h> |
30 | #include <linux/uaccess.h> | 30 | #include <linux/uaccess.h> |
31 | #include <linux/fb.h> | 31 | #include <linux/fb.h> |
32 | #include <linux/init.h> | 32 | #include <linux/init.h> |
33 | 33 | ||
34 | #include <asm/abs_addr.h> | 34 | #include <asm/abs_addr.h> |
35 | #include <asm/lv1call.h> | 35 | #include <asm/lv1call.h> |
36 | #include <asm/ps3av.h> | 36 | #include <asm/ps3av.h> |
37 | #include <asm/ps3fb.h> | 37 | #include <asm/ps3fb.h> |
38 | #include <asm/ps3.h> | 38 | #include <asm/ps3.h> |
39 | 39 | ||
40 | 40 | ||
41 | #define DEVICE_NAME "ps3fb" | 41 | #define DEVICE_NAME "ps3fb" |
42 | 42 | ||
43 | #define L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC 0x101 | 43 | #define L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC 0x101 |
44 | #define L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP 0x102 | 44 | #define L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP 0x102 |
45 | #define L1GPU_CONTEXT_ATTRIBUTE_FB_SETUP 0x600 | 45 | #define L1GPU_CONTEXT_ATTRIBUTE_FB_SETUP 0x600 |
46 | #define L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT 0x601 | 46 | #define L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT 0x601 |
47 | #define L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT_SYNC 0x602 | 47 | #define L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT_SYNC 0x602 |
48 | 48 | ||
49 | #define L1GPU_FB_BLIT_WAIT_FOR_COMPLETION (1ULL << 32) | 49 | #define L1GPU_FB_BLIT_WAIT_FOR_COMPLETION (1ULL << 32) |
50 | 50 | ||
51 | #define L1GPU_DISPLAY_SYNC_HSYNC 1 | 51 | #define L1GPU_DISPLAY_SYNC_HSYNC 1 |
52 | #define L1GPU_DISPLAY_SYNC_VSYNC 2 | 52 | #define L1GPU_DISPLAY_SYNC_VSYNC 2 |
53 | 53 | ||
54 | #define GPU_CMD_BUF_SIZE (2 * 1024 * 1024) | 54 | #define GPU_CMD_BUF_SIZE (2 * 1024 * 1024) |
55 | #define GPU_FB_START (64 * 1024) | 55 | #define GPU_FB_START (64 * 1024) |
56 | #define GPU_IOIF (0x0d000000UL) | 56 | #define GPU_IOIF (0x0d000000UL) |
57 | #define GPU_ALIGN_UP(x) _ALIGN_UP((x), 64) | 57 | #define GPU_ALIGN_UP(x) _ALIGN_UP((x), 64) |
58 | #define GPU_MAX_LINE_LENGTH (65536 - 64) | 58 | #define GPU_MAX_LINE_LENGTH (65536 - 64) |
59 | 59 | ||
60 | #define GPU_INTR_STATUS_VSYNC_0 0 /* vsync on head A */ | 60 | #define GPU_INTR_STATUS_VSYNC_0 0 /* vsync on head A */ |
61 | #define GPU_INTR_STATUS_VSYNC_1 1 /* vsync on head B */ | 61 | #define GPU_INTR_STATUS_VSYNC_1 1 /* vsync on head B */ |
62 | #define GPU_INTR_STATUS_FLIP_0 3 /* flip head A */ | 62 | #define GPU_INTR_STATUS_FLIP_0 3 /* flip head A */ |
63 | #define GPU_INTR_STATUS_FLIP_1 4 /* flip head B */ | 63 | #define GPU_INTR_STATUS_FLIP_1 4 /* flip head B */ |
64 | #define GPU_INTR_STATUS_QUEUE_0 5 /* queue head A */ | 64 | #define GPU_INTR_STATUS_QUEUE_0 5 /* queue head A */ |
65 | #define GPU_INTR_STATUS_QUEUE_1 6 /* queue head B */ | 65 | #define GPU_INTR_STATUS_QUEUE_1 6 /* queue head B */ |
66 | 66 | ||
67 | #define GPU_DRIVER_INFO_VERSION 0x211 | 67 | #define GPU_DRIVER_INFO_VERSION 0x211 |
68 | 68 | ||
69 | /* gpu internals */ | 69 | /* gpu internals */ |
70 | struct display_head { | 70 | struct display_head { |
71 | u64 be_time_stamp; | 71 | u64 be_time_stamp; |
72 | u32 status; | 72 | u32 status; |
73 | u32 offset; | 73 | u32 offset; |
74 | u32 res1; | 74 | u32 res1; |
75 | u32 res2; | 75 | u32 res2; |
76 | u32 field; | 76 | u32 field; |
77 | u32 reserved1; | 77 | u32 reserved1; |
78 | 78 | ||
79 | u64 res3; | 79 | u64 res3; |
80 | u32 raster; | 80 | u32 raster; |
81 | 81 | ||
82 | u64 vblank_count; | 82 | u64 vblank_count; |
83 | u32 field_vsync; | 83 | u32 field_vsync; |
84 | u32 reserved2; | 84 | u32 reserved2; |
85 | }; | 85 | }; |
86 | 86 | ||
87 | struct gpu_irq { | 87 | struct gpu_irq { |
88 | u32 irq_outlet; | 88 | u32 irq_outlet; |
89 | u32 status; | 89 | u32 status; |
90 | u32 mask; | 90 | u32 mask; |
91 | u32 video_cause; | 91 | u32 video_cause; |
92 | u32 graph_cause; | 92 | u32 graph_cause; |
93 | u32 user_cause; | 93 | u32 user_cause; |
94 | 94 | ||
95 | u32 res1; | 95 | u32 res1; |
96 | u64 res2; | 96 | u64 res2; |
97 | 97 | ||
98 | u32 reserved[4]; | 98 | u32 reserved[4]; |
99 | }; | 99 | }; |
100 | 100 | ||
101 | struct gpu_driver_info { | 101 | struct gpu_driver_info { |
102 | u32 version_driver; | 102 | u32 version_driver; |
103 | u32 version_gpu; | 103 | u32 version_gpu; |
104 | u32 memory_size; | 104 | u32 memory_size; |
105 | u32 hardware_channel; | 105 | u32 hardware_channel; |
106 | 106 | ||
107 | u32 nvcore_frequency; | 107 | u32 nvcore_frequency; |
108 | u32 memory_frequency; | 108 | u32 memory_frequency; |
109 | 109 | ||
110 | u32 reserved[1063]; | 110 | u32 reserved[1063]; |
111 | struct display_head display_head[8]; | 111 | struct display_head display_head[8]; |
112 | struct gpu_irq irq; | 112 | struct gpu_irq irq; |
113 | }; | 113 | }; |
114 | 114 | ||
115 | struct ps3fb_priv { | 115 | struct ps3fb_priv { |
116 | unsigned int irq_no; | 116 | unsigned int irq_no; |
117 | 117 | ||
118 | u64 context_handle, memory_handle; | 118 | u64 context_handle, memory_handle; |
119 | struct gpu_driver_info *dinfo; | 119 | struct gpu_driver_info *dinfo; |
120 | 120 | ||
121 | u64 vblank_count; /* frame count */ | 121 | u64 vblank_count; /* frame count */ |
122 | wait_queue_head_t wait_vsync; | 122 | wait_queue_head_t wait_vsync; |
123 | 123 | ||
124 | atomic_t ext_flip; /* on/off flip with vsync */ | 124 | atomic_t ext_flip; /* on/off flip with vsync */ |
125 | atomic_t f_count; /* fb_open count */ | 125 | atomic_t f_count; /* fb_open count */ |
126 | int is_blanked; | 126 | int is_blanked; |
127 | int is_kicked; | 127 | int is_kicked; |
128 | struct task_struct *task; | 128 | struct task_struct *task; |
129 | }; | 129 | }; |
130 | static struct ps3fb_priv ps3fb; | 130 | static struct ps3fb_priv ps3fb; |
131 | 131 | ||
132 | struct ps3fb_par { | 132 | struct ps3fb_par { |
133 | u32 pseudo_palette[16]; | 133 | u32 pseudo_palette[16]; |
134 | int mode_id, new_mode_id; | 134 | int mode_id, new_mode_id; |
135 | unsigned int num_frames; /* num of frame buffers */ | 135 | unsigned int num_frames; /* num of frame buffers */ |
136 | unsigned int width; | 136 | unsigned int width; |
137 | unsigned int height; | 137 | unsigned int height; |
138 | unsigned int ddr_line_length; | 138 | unsigned int ddr_line_length; |
139 | unsigned int ddr_frame_size; | 139 | unsigned int ddr_frame_size; |
140 | unsigned int xdr_frame_size; | 140 | unsigned int xdr_frame_size; |
141 | unsigned int full_offset; /* start of fullscreen DDR fb */ | 141 | unsigned int full_offset; /* start of fullscreen DDR fb */ |
142 | unsigned int fb_offset; /* start of actual DDR fb */ | 142 | unsigned int fb_offset; /* start of actual DDR fb */ |
143 | unsigned int pan_offset; | 143 | unsigned int pan_offset; |
144 | }; | 144 | }; |
145 | 145 | ||
146 | 146 | ||
147 | #define FIRST_NATIVE_MODE_INDEX 10 | 147 | #define FIRST_NATIVE_MODE_INDEX 10 |
148 | 148 | ||
149 | static const struct fb_videomode ps3fb_modedb[] = { | 149 | static const struct fb_videomode ps3fb_modedb[] = { |
150 | /* 60 Hz broadcast modes (modes "1" to "5") */ | 150 | /* 60 Hz broadcast modes (modes "1" to "5") */ |
151 | { | 151 | { |
152 | /* 480i */ | 152 | /* 480i */ |
153 | "480i", 60, 576, 384, 74074, 130, 89, 78, 57, 63, 6, | 153 | "480i", 60, 576, 384, 74074, 130, 89, 78, 57, 63, 6, |
154 | FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | 154 | FB_SYNC_BROADCAST, FB_VMODE_INTERLACED |
155 | }, { | 155 | }, { |
156 | /* 480p */ | 156 | /* 480p */ |
157 | "480p", 60, 576, 384, 37037, 130, 89, 78, 57, 63, 6, | 157 | "480p", 60, 576, 384, 37037, 130, 89, 78, 57, 63, 6, |
158 | FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | 158 | FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED |
159 | }, { | 159 | }, { |
160 | /* 720p */ | 160 | /* 720p */ |
161 | "720p", 60, 1124, 644, 13481, 298, 148, 57, 44, 80, 5, | 161 | "720p", 60, 1124, 644, 13481, 298, 148, 57, 44, 80, 5, |
162 | FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | 162 | FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED |
163 | }, { | 163 | }, { |
164 | /* 1080i */ | 164 | /* 1080i */ |
165 | "1080i", 60, 1688, 964, 13481, 264, 160, 94, 62, 88, 5, | 165 | "1080i", 60, 1688, 964, 13481, 264, 160, 94, 62, 88, 5, |
166 | FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | 166 | FB_SYNC_BROADCAST, FB_VMODE_INTERLACED |
167 | }, { | 167 | }, { |
168 | /* 1080p */ | 168 | /* 1080p */ |
169 | "1080p", 60, 1688, 964, 6741, 264, 160, 94, 62, 88, 5, | 169 | "1080p", 60, 1688, 964, 6741, 264, 160, 94, 62, 88, 5, |
170 | FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | 170 | FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED |
171 | }, | 171 | }, |
172 | 172 | ||
173 | /* 50 Hz broadcast modes (modes "6" to "10") */ | 173 | /* 50 Hz broadcast modes (modes "6" to "10") */ |
174 | { | 174 | { |
175 | /* 576i */ | 175 | /* 576i */ |
176 | "576i", 50, 576, 460, 74074, 142, 83, 97, 63, 63, 5, | 176 | "576i", 50, 576, 460, 74074, 142, 83, 97, 63, 63, 5, |
177 | FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | 177 | FB_SYNC_BROADCAST, FB_VMODE_INTERLACED |
178 | }, { | 178 | }, { |
179 | /* 576p */ | 179 | /* 576p */ |
180 | "576p", 50, 576, 460, 37037, 142, 83, 97, 63, 63, 5, | 180 | "576p", 50, 576, 460, 37037, 142, 83, 97, 63, 63, 5, |
181 | FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | 181 | FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED |
182 | }, { | 182 | }, { |
183 | /* 720p */ | 183 | /* 720p */ |
184 | "720p", 50, 1124, 644, 13468, 298, 478, 57, 44, 80, 5, | 184 | "720p", 50, 1124, 644, 13468, 298, 478, 57, 44, 80, 5, |
185 | FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | 185 | FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED |
186 | }, { | 186 | }, { |
187 | /* 1080i */ | 187 | /* 1080i */ |
188 | "1080i", 50, 1688, 964, 13468, 264, 600, 94, 62, 88, 5, | 188 | "1080i", 50, 1688, 964, 13468, 264, 600, 94, 62, 88, 5, |
189 | FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | 189 | FB_SYNC_BROADCAST, FB_VMODE_INTERLACED |
190 | }, { | 190 | }, { |
191 | /* 1080p */ | 191 | /* 1080p */ |
192 | "1080p", 50, 1688, 964, 6734, 264, 600, 94, 62, 88, 5, | 192 | "1080p", 50, 1688, 964, 6734, 264, 600, 94, 62, 88, 5, |
193 | FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | 193 | FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED |
194 | }, | 194 | }, |
195 | 195 | ||
196 | [FIRST_NATIVE_MODE_INDEX] = | 196 | [FIRST_NATIVE_MODE_INDEX] = |
197 | /* 60 Hz broadcast modes (full resolution versions of modes "1" to "5") */ | 197 | /* 60 Hz broadcast modes (full resolution versions of modes "1" to "5") */ |
198 | { | 198 | { |
199 | /* 480if */ | 199 | /* 480if */ |
200 | "480if", 60, 720, 480, 74074, 58, 17, 30, 9, 63, 6, | 200 | "480if", 60, 720, 480, 74074, 58, 17, 30, 9, 63, 6, |
201 | FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | 201 | FB_SYNC_BROADCAST, FB_VMODE_INTERLACED |
202 | }, { | 202 | }, { |
203 | /* 480pf */ | 203 | /* 480pf */ |
204 | "480pf", 60, 720, 480, 37037, 58, 17, 30, 9, 63, 6, | 204 | "480pf", 60, 720, 480, 37037, 58, 17, 30, 9, 63, 6, |
205 | FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | 205 | FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED |
206 | }, { | 206 | }, { |
207 | /* 720pf */ | 207 | /* 720pf */ |
208 | "720pf", 60, 1280, 720, 13481, 220, 70, 19, 6, 80, 5, | 208 | "720pf", 60, 1280, 720, 13481, 220, 70, 19, 6, 80, 5, |
209 | FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | 209 | FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED |
210 | }, { | 210 | }, { |
211 | /* 1080if */ | 211 | /* 1080if */ |
212 | "1080if", 60, 1920, 1080, 13481, 148, 44, 36, 4, 88, 5, | 212 | "1080if", 60, 1920, 1080, 13481, 148, 44, 36, 4, 88, 5, |
213 | FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | 213 | FB_SYNC_BROADCAST, FB_VMODE_INTERLACED |
214 | }, { | 214 | }, { |
215 | /* 1080pf */ | 215 | /* 1080pf */ |
216 | "1080pf", 60, 1920, 1080, 6741, 148, 44, 36, 4, 88, 5, | 216 | "1080pf", 60, 1920, 1080, 6741, 148, 44, 36, 4, 88, 5, |
217 | FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | 217 | FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED |
218 | }, | 218 | }, |
219 | 219 | ||
220 | /* 50 Hz broadcast modes (full resolution versions of modes "6" to "10") */ | 220 | /* 50 Hz broadcast modes (full resolution versions of modes "6" to "10") */ |
221 | { | 221 | { |
222 | /* 576if */ | 222 | /* 576if */ |
223 | "576if", 50, 720, 576, 74074, 70, 11, 39, 5, 63, 5, | 223 | "576if", 50, 720, 576, 74074, 70, 11, 39, 5, 63, 5, |
224 | FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | 224 | FB_SYNC_BROADCAST, FB_VMODE_INTERLACED |
225 | }, { | 225 | }, { |
226 | /* 576pf */ | 226 | /* 576pf */ |
227 | "576pf", 50, 720, 576, 37037, 70, 11, 39, 5, 63, 5, | 227 | "576pf", 50, 720, 576, 37037, 70, 11, 39, 5, 63, 5, |
228 | FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | 228 | FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED |
229 | }, { | 229 | }, { |
230 | /* 720pf */ | 230 | /* 720pf */ |
231 | "720pf", 50, 1280, 720, 13468, 220, 400, 19, 6, 80, 5, | 231 | "720pf", 50, 1280, 720, 13468, 220, 400, 19, 6, 80, 5, |
232 | FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | 232 | FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED |
233 | }, { | 233 | }, { |
234 | /* 1080if */ | 234 | /* 1080if */ |
235 | "1080if", 50, 1920, 1080, 13468, 148, 484, 36, 4, 88, 5, | 235 | "1080if", 50, 1920, 1080, 13468, 148, 484, 36, 4, 88, 5, |
236 | FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | 236 | FB_SYNC_BROADCAST, FB_VMODE_INTERLACED |
237 | }, { | 237 | }, { |
238 | /* 1080pf */ | 238 | /* 1080pf */ |
239 | "1080pf", 50, 1920, 1080, 6734, 148, 484, 36, 4, 88, 5, | 239 | "1080pf", 50, 1920, 1080, 6734, 148, 484, 36, 4, 88, 5, |
240 | FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | 240 | FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED |
241 | }, | 241 | }, |
242 | 242 | ||
243 | /* VESA modes (modes "11" to "13") */ | 243 | /* VESA modes (modes "11" to "13") */ |
244 | { | 244 | { |
245 | /* WXGA */ | 245 | /* WXGA */ |
246 | "wxga", 60, 1280, 768, 12924, 160, 24, 29, 3, 136, 6, | 246 | "wxga", 60, 1280, 768, 12924, 160, 24, 29, 3, 136, 6, |
247 | 0, FB_VMODE_NONINTERLACED, | 247 | 0, FB_VMODE_NONINTERLACED, |
248 | FB_MODE_IS_VESA | 248 | FB_MODE_IS_VESA |
249 | }, { | 249 | }, { |
250 | /* SXGA */ | 250 | /* SXGA */ |
251 | "sxga", 60, 1280, 1024, 9259, 248, 48, 38, 1, 112, 3, | 251 | "sxga", 60, 1280, 1024, 9259, 248, 48, 38, 1, 112, 3, |
252 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, | 252 | FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, |
253 | FB_MODE_IS_VESA | 253 | FB_MODE_IS_VESA |
254 | }, { | 254 | }, { |
255 | /* WUXGA */ | 255 | /* WUXGA */ |
256 | "wuxga", 60, 1920, 1200, 6494, 80, 48, 26, 3, 32, 6, | 256 | "wuxga", 60, 1920, 1200, 6494, 80, 48, 26, 3, 32, 6, |
257 | FB_SYNC_HOR_HIGH_ACT, FB_VMODE_NONINTERLACED, | 257 | FB_SYNC_HOR_HIGH_ACT, FB_VMODE_NONINTERLACED, |
258 | FB_MODE_IS_VESA | 258 | FB_MODE_IS_VESA |
259 | } | 259 | } |
260 | }; | 260 | }; |
261 | 261 | ||
262 | 262 | ||
263 | #define HEAD_A | 263 | #define HEAD_A |
264 | #define HEAD_B | 264 | #define HEAD_B |
265 | 265 | ||
266 | #define BPP 4 /* number of bytes per pixel */ | 266 | #define BPP 4 /* number of bytes per pixel */ |
267 | 267 | ||
268 | 268 | ||
269 | static int ps3fb_mode; | 269 | static int ps3fb_mode; |
270 | module_param(ps3fb_mode, int, 0); | 270 | module_param(ps3fb_mode, int, 0); |
271 | 271 | ||
272 | static char *mode_option __devinitdata; | 272 | static char *mode_option __devinitdata; |
273 | 273 | ||
274 | static int ps3fb_cmp_mode(const struct fb_videomode *vmode, | 274 | static int ps3fb_cmp_mode(const struct fb_videomode *vmode, |
275 | const struct fb_var_screeninfo *var) | 275 | const struct fb_var_screeninfo *var) |
276 | { | 276 | { |
277 | long xres, yres, left_margin, right_margin, upper_margin, lower_margin; | 277 | long xres, yres, left_margin, right_margin, upper_margin, lower_margin; |
278 | long dx, dy; | 278 | long dx, dy; |
279 | 279 | ||
280 | /* maximum values */ | 280 | /* maximum values */ |
281 | if (var->xres > vmode->xres || var->yres > vmode->yres || | 281 | if (var->xres > vmode->xres || var->yres > vmode->yres || |
282 | var->pixclock > vmode->pixclock || | 282 | var->pixclock > vmode->pixclock || |
283 | var->hsync_len > vmode->hsync_len || | 283 | var->hsync_len > vmode->hsync_len || |
284 | var->vsync_len > vmode->vsync_len) | 284 | var->vsync_len > vmode->vsync_len) |
285 | return -1; | 285 | return -1; |
286 | 286 | ||
287 | /* progressive/interlaced must match */ | 287 | /* progressive/interlaced must match */ |
288 | if ((var->vmode & FB_VMODE_MASK) != vmode->vmode) | 288 | if ((var->vmode & FB_VMODE_MASK) != vmode->vmode) |
289 | return -1; | 289 | return -1; |
290 | 290 | ||
291 | /* minimum resolution */ | 291 | /* minimum resolution */ |
292 | xres = max(var->xres, 1U); | 292 | xres = max(var->xres, 1U); |
293 | yres = max(var->yres, 1U); | 293 | yres = max(var->yres, 1U); |
294 | 294 | ||
295 | /* minimum margins */ | 295 | /* minimum margins */ |
296 | left_margin = max(var->left_margin, vmode->left_margin); | 296 | left_margin = max(var->left_margin, vmode->left_margin); |
297 | right_margin = max(var->right_margin, vmode->right_margin); | 297 | right_margin = max(var->right_margin, vmode->right_margin); |
298 | upper_margin = max(var->upper_margin, vmode->upper_margin); | 298 | upper_margin = max(var->upper_margin, vmode->upper_margin); |
299 | lower_margin = max(var->lower_margin, vmode->lower_margin); | 299 | lower_margin = max(var->lower_margin, vmode->lower_margin); |
300 | 300 | ||
301 | /* resolution + margins may not exceed native parameters */ | 301 | /* resolution + margins may not exceed native parameters */ |
302 | dx = ((long)vmode->left_margin + (long)vmode->xres + | 302 | dx = ((long)vmode->left_margin + (long)vmode->xres + |
303 | (long)vmode->right_margin) - | 303 | (long)vmode->right_margin) - |
304 | (left_margin + xres + right_margin); | 304 | (left_margin + xres + right_margin); |
305 | if (dx < 0) | 305 | if (dx < 0) |
306 | return -1; | 306 | return -1; |
307 | 307 | ||
308 | dy = ((long)vmode->upper_margin + (long)vmode->yres + | 308 | dy = ((long)vmode->upper_margin + (long)vmode->yres + |
309 | (long)vmode->lower_margin) - | 309 | (long)vmode->lower_margin) - |
310 | (upper_margin + yres + lower_margin); | 310 | (upper_margin + yres + lower_margin); |
311 | if (dy < 0) | 311 | if (dy < 0) |
312 | return -1; | 312 | return -1; |
313 | 313 | ||
314 | /* exact match */ | 314 | /* exact match */ |
315 | if (!dx && !dy) | 315 | if (!dx && !dy) |
316 | return 0; | 316 | return 0; |
317 | 317 | ||
318 | /* resolution difference */ | 318 | /* resolution difference */ |
319 | return (vmode->xres - xres) * (vmode->yres - yres); | 319 | return (vmode->xres - xres) * (vmode->yres - yres); |
320 | } | 320 | } |
321 | 321 | ||
322 | static const struct fb_videomode *ps3fb_native_vmode(enum ps3av_mode_num id) | 322 | static const struct fb_videomode *ps3fb_native_vmode(enum ps3av_mode_num id) |
323 | { | 323 | { |
324 | return &ps3fb_modedb[FIRST_NATIVE_MODE_INDEX + id - 1]; | 324 | return &ps3fb_modedb[FIRST_NATIVE_MODE_INDEX + id - 1]; |
325 | } | 325 | } |
326 | 326 | ||
327 | static const struct fb_videomode *ps3fb_vmode(int id) | 327 | static const struct fb_videomode *ps3fb_vmode(int id) |
328 | { | 328 | { |
329 | u32 mode = id & PS3AV_MODE_MASK; | 329 | u32 mode = id & PS3AV_MODE_MASK; |
330 | 330 | ||
331 | if (mode < PS3AV_MODE_480I || mode > PS3AV_MODE_WUXGA) | 331 | if (mode < PS3AV_MODE_480I || mode > PS3AV_MODE_WUXGA) |
332 | return NULL; | 332 | return NULL; |
333 | 333 | ||
334 | if (mode <= PS3AV_MODE_1080P50 && !(id & PS3AV_MODE_FULL)) { | 334 | if (mode <= PS3AV_MODE_1080P50 && !(id & PS3AV_MODE_FULL)) { |
335 | /* Non-fullscreen broadcast mode */ | 335 | /* Non-fullscreen broadcast mode */ |
336 | return &ps3fb_modedb[mode - 1]; | 336 | return &ps3fb_modedb[mode - 1]; |
337 | } | 337 | } |
338 | 338 | ||
339 | return ps3fb_native_vmode(mode); | 339 | return ps3fb_native_vmode(mode); |
340 | } | 340 | } |
341 | 341 | ||
342 | static unsigned int ps3fb_find_mode(struct fb_var_screeninfo *var, | 342 | static unsigned int ps3fb_find_mode(struct fb_var_screeninfo *var, |
343 | u32 *ddr_line_length, u32 *xdr_line_length) | 343 | u32 *ddr_line_length, u32 *xdr_line_length) |
344 | { | 344 | { |
345 | unsigned int id, best_id; | 345 | unsigned int id, best_id; |
346 | int diff, best_diff; | 346 | int diff, best_diff; |
347 | const struct fb_videomode *vmode; | 347 | const struct fb_videomode *vmode; |
348 | long gap; | 348 | long gap; |
349 | 349 | ||
350 | best_id = 0; | 350 | best_id = 0; |
351 | best_diff = INT_MAX; | 351 | best_diff = INT_MAX; |
352 | pr_debug("%s: wanted %u [%u] %u x %u [%u] %u\n", __func__, | 352 | pr_debug("%s: wanted %u [%u] %u x %u [%u] %u\n", __func__, |
353 | var->left_margin, var->xres, var->right_margin, | 353 | var->left_margin, var->xres, var->right_margin, |
354 | var->upper_margin, var->yres, var->lower_margin); | 354 | var->upper_margin, var->yres, var->lower_margin); |
355 | for (id = PS3AV_MODE_480I; id <= PS3AV_MODE_WUXGA; id++) { | 355 | for (id = PS3AV_MODE_480I; id <= PS3AV_MODE_WUXGA; id++) { |
356 | vmode = ps3fb_native_vmode(id); | 356 | vmode = ps3fb_native_vmode(id); |
357 | diff = ps3fb_cmp_mode(vmode, var); | 357 | diff = ps3fb_cmp_mode(vmode, var); |
358 | pr_debug("%s: mode %u: %u [%u] %u x %u [%u] %u: diff = %d\n", | 358 | pr_debug("%s: mode %u: %u [%u] %u x %u [%u] %u: diff = %d\n", |
359 | __func__, id, vmode->left_margin, vmode->xres, | 359 | __func__, id, vmode->left_margin, vmode->xres, |
360 | vmode->right_margin, vmode->upper_margin, | 360 | vmode->right_margin, vmode->upper_margin, |
361 | vmode->yres, vmode->lower_margin, diff); | 361 | vmode->yres, vmode->lower_margin, diff); |
362 | if (diff < 0) | 362 | if (diff < 0) |
363 | continue; | 363 | continue; |
364 | if (diff < best_diff) { | 364 | if (diff < best_diff) { |
365 | best_id = id; | 365 | best_id = id; |
366 | if (!diff) | 366 | if (!diff) |
367 | break; | 367 | break; |
368 | best_diff = diff; | 368 | best_diff = diff; |
369 | } | 369 | } |
370 | } | 370 | } |
371 | 371 | ||
372 | if (!best_id) { | 372 | if (!best_id) { |
373 | pr_debug("%s: no suitable mode found\n", __func__); | 373 | pr_debug("%s: no suitable mode found\n", __func__); |
374 | return 0; | 374 | return 0; |
375 | } | 375 | } |
376 | 376 | ||
377 | id = best_id; | 377 | id = best_id; |
378 | vmode = ps3fb_native_vmode(id); | 378 | vmode = ps3fb_native_vmode(id); |
379 | 379 | ||
380 | *ddr_line_length = vmode->xres * BPP; | 380 | *ddr_line_length = vmode->xres * BPP; |
381 | 381 | ||
382 | /* minimum resolution */ | 382 | /* minimum resolution */ |
383 | if (!var->xres) | 383 | if (!var->xres) |
384 | var->xres = 1; | 384 | var->xres = 1; |
385 | if (!var->yres) | 385 | if (!var->yres) |
386 | var->yres = 1; | 386 | var->yres = 1; |
387 | 387 | ||
388 | /* minimum virtual resolution */ | 388 | /* minimum virtual resolution */ |
389 | if (var->xres_virtual < var->xres) | 389 | if (var->xres_virtual < var->xres) |
390 | var->xres_virtual = var->xres; | 390 | var->xres_virtual = var->xres; |
391 | if (var->yres_virtual < var->yres) | 391 | if (var->yres_virtual < var->yres) |
392 | var->yres_virtual = var->yres; | 392 | var->yres_virtual = var->yres; |
393 | 393 | ||
394 | /* minimum margins */ | 394 | /* minimum margins */ |
395 | if (var->left_margin < vmode->left_margin) | 395 | if (var->left_margin < vmode->left_margin) |
396 | var->left_margin = vmode->left_margin; | 396 | var->left_margin = vmode->left_margin; |
397 | if (var->right_margin < vmode->right_margin) | 397 | if (var->right_margin < vmode->right_margin) |
398 | var->right_margin = vmode->right_margin; | 398 | var->right_margin = vmode->right_margin; |
399 | if (var->upper_margin < vmode->upper_margin) | 399 | if (var->upper_margin < vmode->upper_margin) |
400 | var->upper_margin = vmode->upper_margin; | 400 | var->upper_margin = vmode->upper_margin; |
401 | if (var->lower_margin < vmode->lower_margin) | 401 | if (var->lower_margin < vmode->lower_margin) |
402 | var->lower_margin = vmode->lower_margin; | 402 | var->lower_margin = vmode->lower_margin; |
403 | 403 | ||
404 | /* extra margins */ | 404 | /* extra margins */ |
405 | gap = ((long)vmode->left_margin + (long)vmode->xres + | 405 | gap = ((long)vmode->left_margin + (long)vmode->xres + |
406 | (long)vmode->right_margin) - | 406 | (long)vmode->right_margin) - |
407 | ((long)var->left_margin + (long)var->xres + | 407 | ((long)var->left_margin + (long)var->xres + |
408 | (long)var->right_margin); | 408 | (long)var->right_margin); |
409 | if (gap > 0) { | 409 | if (gap > 0) { |
410 | var->left_margin += gap/2; | 410 | var->left_margin += gap/2; |
411 | var->right_margin += (gap+1)/2; | 411 | var->right_margin += (gap+1)/2; |
412 | pr_debug("%s: rounded up H to %u [%u] %u\n", __func__, | 412 | pr_debug("%s: rounded up H to %u [%u] %u\n", __func__, |
413 | var->left_margin, var->xres, var->right_margin); | 413 | var->left_margin, var->xres, var->right_margin); |
414 | } | 414 | } |
415 | 415 | ||
416 | gap = ((long)vmode->upper_margin + (long)vmode->yres + | 416 | gap = ((long)vmode->upper_margin + (long)vmode->yres + |
417 | (long)vmode->lower_margin) - | 417 | (long)vmode->lower_margin) - |
418 | ((long)var->upper_margin + (long)var->yres + | 418 | ((long)var->upper_margin + (long)var->yres + |
419 | (long)var->lower_margin); | 419 | (long)var->lower_margin); |
420 | if (gap > 0) { | 420 | if (gap > 0) { |
421 | var->upper_margin += gap/2; | 421 | var->upper_margin += gap/2; |
422 | var->lower_margin += (gap+1)/2; | 422 | var->lower_margin += (gap+1)/2; |
423 | pr_debug("%s: rounded up V to %u [%u] %u\n", __func__, | 423 | pr_debug("%s: rounded up V to %u [%u] %u\n", __func__, |
424 | var->upper_margin, var->yres, var->lower_margin); | 424 | var->upper_margin, var->yres, var->lower_margin); |
425 | } | 425 | } |
426 | 426 | ||
427 | /* fixed fields */ | 427 | /* fixed fields */ |
428 | var->pixclock = vmode->pixclock; | 428 | var->pixclock = vmode->pixclock; |
429 | var->hsync_len = vmode->hsync_len; | 429 | var->hsync_len = vmode->hsync_len; |
430 | var->vsync_len = vmode->vsync_len; | 430 | var->vsync_len = vmode->vsync_len; |
431 | var->sync = vmode->sync; | 431 | var->sync = vmode->sync; |
432 | 432 | ||
433 | if (ps3_compare_firmware_version(1, 9, 0) >= 0) { | 433 | if (ps3_compare_firmware_version(1, 9, 0) >= 0) { |
434 | *xdr_line_length = GPU_ALIGN_UP(var->xres_virtual * BPP); | 434 | *xdr_line_length = GPU_ALIGN_UP(var->xres_virtual * BPP); |
435 | if (*xdr_line_length > GPU_MAX_LINE_LENGTH) | 435 | if (*xdr_line_length > GPU_MAX_LINE_LENGTH) |
436 | *xdr_line_length = GPU_MAX_LINE_LENGTH; | 436 | *xdr_line_length = GPU_MAX_LINE_LENGTH; |
437 | } else | 437 | } else |
438 | *xdr_line_length = *ddr_line_length; | 438 | *xdr_line_length = *ddr_line_length; |
439 | 439 | ||
440 | if (vmode->sync & FB_SYNC_BROADCAST) { | 440 | if (vmode->sync & FB_SYNC_BROADCAST) { |
441 | /* Full broadcast modes have the full mode bit set */ | 441 | /* Full broadcast modes have the full mode bit set */ |
442 | if (vmode->xres == var->xres && vmode->yres == var->yres) | 442 | if (vmode->xres == var->xres && vmode->yres == var->yres) |
443 | id |= PS3AV_MODE_FULL; | 443 | id |= PS3AV_MODE_FULL; |
444 | } | 444 | } |
445 | 445 | ||
446 | pr_debug("%s: mode %u\n", __func__, id); | 446 | pr_debug("%s: mode %u\n", __func__, id); |
447 | return id; | 447 | return id; |
448 | } | 448 | } |
449 | 449 | ||
450 | static void ps3fb_sync_image(struct device *dev, u64 frame_offset, | 450 | static void ps3fb_sync_image(struct device *dev, u64 frame_offset, |
451 | u64 dst_offset, u64 src_offset, u32 width, | 451 | u64 dst_offset, u64 src_offset, u32 width, |
452 | u32 height, u32 dst_line_length, | 452 | u32 height, u32 dst_line_length, |
453 | u32 src_line_length) | 453 | u32 src_line_length) |
454 | { | 454 | { |
455 | int status; | 455 | int status; |
456 | u64 line_length; | 456 | u64 line_length; |
457 | 457 | ||
458 | line_length = dst_line_length; | 458 | line_length = dst_line_length; |
459 | if (src_line_length != dst_line_length) | 459 | if (src_line_length != dst_line_length) |
460 | line_length |= (u64)src_line_length << 32; | 460 | line_length |= (u64)src_line_length << 32; |
461 | 461 | ||
462 | src_offset += GPU_FB_START; | 462 | src_offset += GPU_FB_START; |
463 | |||
464 | mutex_lock(&ps3_gpu_mutex); | ||
463 | status = lv1_gpu_context_attribute(ps3fb.context_handle, | 465 | status = lv1_gpu_context_attribute(ps3fb.context_handle, |
464 | L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT, | 466 | L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT, |
465 | dst_offset, GPU_IOIF + src_offset, | 467 | dst_offset, GPU_IOIF + src_offset, |
466 | L1GPU_FB_BLIT_WAIT_FOR_COMPLETION | | 468 | L1GPU_FB_BLIT_WAIT_FOR_COMPLETION | |
467 | (width << 16) | height, | 469 | (width << 16) | height, |
468 | line_length); | 470 | line_length); |
471 | mutex_unlock(&ps3_gpu_mutex); | ||
472 | |||
469 | if (status) | 473 | if (status) |
470 | dev_err(dev, | 474 | dev_err(dev, |
471 | "%s: lv1_gpu_context_attribute FB_BLIT failed: %d\n", | 475 | "%s: lv1_gpu_context_attribute FB_BLIT failed: %d\n", |
472 | __func__, status); | 476 | __func__, status); |
473 | #ifdef HEAD_A | 477 | #ifdef HEAD_A |
474 | status = lv1_gpu_context_attribute(ps3fb.context_handle, | 478 | status = lv1_gpu_context_attribute(ps3fb.context_handle, |
475 | L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP, | 479 | L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP, |
476 | 0, frame_offset, 0, 0); | 480 | 0, frame_offset, 0, 0); |
477 | if (status) | 481 | if (status) |
478 | dev_err(dev, "%s: lv1_gpu_context_attribute FLIP failed: %d\n", | 482 | dev_err(dev, "%s: lv1_gpu_context_attribute FLIP failed: %d\n", |
479 | __func__, status); | 483 | __func__, status); |
480 | #endif | 484 | #endif |
481 | #ifdef HEAD_B | 485 | #ifdef HEAD_B |
482 | status = lv1_gpu_context_attribute(ps3fb.context_handle, | 486 | status = lv1_gpu_context_attribute(ps3fb.context_handle, |
483 | L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP, | 487 | L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_FLIP, |
484 | 1, frame_offset, 0, 0); | 488 | 1, frame_offset, 0, 0); |
485 | if (status) | 489 | if (status) |
486 | dev_err(dev, "%s: lv1_gpu_context_attribute FLIP failed: %d\n", | 490 | dev_err(dev, "%s: lv1_gpu_context_attribute FLIP failed: %d\n", |
487 | __func__, status); | 491 | __func__, status); |
488 | #endif | 492 | #endif |
489 | } | 493 | } |
490 | 494 | ||
491 | static int ps3fb_sync(struct fb_info *info, u32 frame) | 495 | static int ps3fb_sync(struct fb_info *info, u32 frame) |
492 | { | 496 | { |
493 | struct ps3fb_par *par = info->par; | 497 | struct ps3fb_par *par = info->par; |
494 | int error = 0; | 498 | int error = 0; |
495 | u64 ddr_base, xdr_base; | 499 | u64 ddr_base, xdr_base; |
496 | 500 | ||
497 | if (frame > par->num_frames - 1) { | 501 | if (frame > par->num_frames - 1) { |
498 | dev_dbg(info->device, "%s: invalid frame number (%u)\n", | 502 | dev_dbg(info->device, "%s: invalid frame number (%u)\n", |
499 | __func__, frame); | 503 | __func__, frame); |
500 | error = -EINVAL; | 504 | error = -EINVAL; |
501 | goto out; | 505 | goto out; |
502 | } | 506 | } |
503 | 507 | ||
504 | xdr_base = frame * par->xdr_frame_size; | 508 | xdr_base = frame * par->xdr_frame_size; |
505 | ddr_base = frame * par->ddr_frame_size; | 509 | ddr_base = frame * par->ddr_frame_size; |
506 | 510 | ||
507 | ps3fb_sync_image(info->device, ddr_base + par->full_offset, | 511 | ps3fb_sync_image(info->device, ddr_base + par->full_offset, |
508 | ddr_base + par->fb_offset, xdr_base + par->pan_offset, | 512 | ddr_base + par->fb_offset, xdr_base + par->pan_offset, |
509 | par->width, par->height, par->ddr_line_length, | 513 | par->width, par->height, par->ddr_line_length, |
510 | info->fix.line_length); | 514 | info->fix.line_length); |
511 | 515 | ||
512 | out: | 516 | out: |
513 | return error; | 517 | return error; |
514 | } | 518 | } |
515 | 519 | ||
516 | static int ps3fb_open(struct fb_info *info, int user) | 520 | static int ps3fb_open(struct fb_info *info, int user) |
517 | { | 521 | { |
518 | atomic_inc(&ps3fb.f_count); | 522 | atomic_inc(&ps3fb.f_count); |
519 | return 0; | 523 | return 0; |
520 | } | 524 | } |
521 | 525 | ||
522 | static int ps3fb_release(struct fb_info *info, int user) | 526 | static int ps3fb_release(struct fb_info *info, int user) |
523 | { | 527 | { |
524 | if (atomic_dec_and_test(&ps3fb.f_count)) { | 528 | if (atomic_dec_and_test(&ps3fb.f_count)) { |
525 | if (atomic_read(&ps3fb.ext_flip)) { | 529 | if (atomic_read(&ps3fb.ext_flip)) { |
526 | atomic_set(&ps3fb.ext_flip, 0); | 530 | atomic_set(&ps3fb.ext_flip, 0); |
527 | if (!try_acquire_console_sem()) { | 531 | if (!try_acquire_console_sem()) { |
528 | ps3fb_sync(info, 0); /* single buffer */ | 532 | ps3fb_sync(info, 0); /* single buffer */ |
529 | release_console_sem(); | 533 | release_console_sem(); |
530 | } | 534 | } |
531 | } | 535 | } |
532 | } | 536 | } |
533 | return 0; | 537 | return 0; |
534 | } | 538 | } |
535 | 539 | ||
536 | /* | 540 | /* |
537 | * Setting the video mode has been split into two parts. | 541 | * Setting the video mode has been split into two parts. |
538 | * First part, xxxfb_check_var, must not write anything | 542 | * First part, xxxfb_check_var, must not write anything |
539 | * to hardware, it should only verify and adjust var. | 543 | * to hardware, it should only verify and adjust var. |
540 | * This means it doesn't alter par but it does use hardware | 544 | * This means it doesn't alter par but it does use hardware |
541 | * data from it to check this var. | 545 | * data from it to check this var. |
542 | */ | 546 | */ |
543 | 547 | ||
544 | static int ps3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | 548 | static int ps3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) |
545 | { | 549 | { |
546 | u32 xdr_line_length, ddr_line_length; | 550 | u32 xdr_line_length, ddr_line_length; |
547 | int mode; | 551 | int mode; |
548 | 552 | ||
549 | mode = ps3fb_find_mode(var, &ddr_line_length, &xdr_line_length); | 553 | mode = ps3fb_find_mode(var, &ddr_line_length, &xdr_line_length); |
550 | if (!mode) | 554 | if (!mode) |
551 | return -EINVAL; | 555 | return -EINVAL; |
552 | 556 | ||
553 | /* Virtual screen */ | 557 | /* Virtual screen */ |
554 | if (var->xres_virtual > xdr_line_length / BPP) { | 558 | if (var->xres_virtual > xdr_line_length / BPP) { |
555 | dev_dbg(info->device, | 559 | dev_dbg(info->device, |
556 | "Horizontal virtual screen size too large\n"); | 560 | "Horizontal virtual screen size too large\n"); |
557 | return -EINVAL; | 561 | return -EINVAL; |
558 | } | 562 | } |
559 | 563 | ||
560 | if (var->xoffset + var->xres > var->xres_virtual || | 564 | if (var->xoffset + var->xres > var->xres_virtual || |
561 | var->yoffset + var->yres > var->yres_virtual) { | 565 | var->yoffset + var->yres > var->yres_virtual) { |
562 | dev_dbg(info->device, "panning out-of-range\n"); | 566 | dev_dbg(info->device, "panning out-of-range\n"); |
563 | return -EINVAL; | 567 | return -EINVAL; |
564 | } | 568 | } |
565 | 569 | ||
566 | /* We support ARGB8888 only */ | 570 | /* We support ARGB8888 only */ |
567 | if (var->bits_per_pixel > 32 || var->grayscale || | 571 | if (var->bits_per_pixel > 32 || var->grayscale || |
568 | var->red.offset > 16 || var->green.offset > 8 || | 572 | var->red.offset > 16 || var->green.offset > 8 || |
569 | var->blue.offset > 0 || var->transp.offset > 24 || | 573 | var->blue.offset > 0 || var->transp.offset > 24 || |
570 | var->red.length > 8 || var->green.length > 8 || | 574 | var->red.length > 8 || var->green.length > 8 || |
571 | var->blue.length > 8 || var->transp.length > 8 || | 575 | var->blue.length > 8 || var->transp.length > 8 || |
572 | var->red.msb_right || var->green.msb_right || | 576 | var->red.msb_right || var->green.msb_right || |
573 | var->blue.msb_right || var->transp.msb_right || var->nonstd) { | 577 | var->blue.msb_right || var->transp.msb_right || var->nonstd) { |
574 | dev_dbg(info->device, "We support ARGB8888 only\n"); | 578 | dev_dbg(info->device, "We support ARGB8888 only\n"); |
575 | return -EINVAL; | 579 | return -EINVAL; |
576 | } | 580 | } |
577 | 581 | ||
578 | var->bits_per_pixel = 32; | 582 | var->bits_per_pixel = 32; |
579 | var->red.offset = 16; | 583 | var->red.offset = 16; |
580 | var->green.offset = 8; | 584 | var->green.offset = 8; |
581 | var->blue.offset = 0; | 585 | var->blue.offset = 0; |
582 | var->transp.offset = 24; | 586 | var->transp.offset = 24; |
583 | var->red.length = 8; | 587 | var->red.length = 8; |
584 | var->green.length = 8; | 588 | var->green.length = 8; |
585 | var->blue.length = 8; | 589 | var->blue.length = 8; |
586 | var->transp.length = 8; | 590 | var->transp.length = 8; |
587 | var->red.msb_right = 0; | 591 | var->red.msb_right = 0; |
588 | var->green.msb_right = 0; | 592 | var->green.msb_right = 0; |
589 | var->blue.msb_right = 0; | 593 | var->blue.msb_right = 0; |
590 | var->transp.msb_right = 0; | 594 | var->transp.msb_right = 0; |
591 | 595 | ||
592 | /* Rotation is not supported */ | 596 | /* Rotation is not supported */ |
593 | if (var->rotate) { | 597 | if (var->rotate) { |
594 | dev_dbg(info->device, "Rotation is not supported\n"); | 598 | dev_dbg(info->device, "Rotation is not supported\n"); |
595 | return -EINVAL; | 599 | return -EINVAL; |
596 | } | 600 | } |
597 | 601 | ||
598 | /* Memory limit */ | 602 | /* Memory limit */ |
599 | if (var->yres_virtual * xdr_line_length > info->fix.smem_len) { | 603 | if (var->yres_virtual * xdr_line_length > info->fix.smem_len) { |
600 | dev_dbg(info->device, "Not enough memory\n"); | 604 | dev_dbg(info->device, "Not enough memory\n"); |
601 | return -ENOMEM; | 605 | return -ENOMEM; |
602 | } | 606 | } |
603 | 607 | ||
604 | var->height = -1; | 608 | var->height = -1; |
605 | var->width = -1; | 609 | var->width = -1; |
606 | 610 | ||
607 | return 0; | 611 | return 0; |
608 | } | 612 | } |
609 | 613 | ||
610 | /* | 614 | /* |
611 | * This routine actually sets the video mode. | 615 | * This routine actually sets the video mode. |
612 | */ | 616 | */ |
613 | 617 | ||
614 | static int ps3fb_set_par(struct fb_info *info) | 618 | static int ps3fb_set_par(struct fb_info *info) |
615 | { | 619 | { |
616 | struct ps3fb_par *par = info->par; | 620 | struct ps3fb_par *par = info->par; |
617 | unsigned int mode, ddr_line_length, xdr_line_length, lines, maxlines; | 621 | unsigned int mode, ddr_line_length, xdr_line_length, lines, maxlines; |
618 | unsigned int ddr_xoff, ddr_yoff, offset; | 622 | unsigned int ddr_xoff, ddr_yoff, offset; |
619 | const struct fb_videomode *vmode; | 623 | const struct fb_videomode *vmode; |
620 | u64 dst; | 624 | u64 dst; |
621 | 625 | ||
622 | mode = ps3fb_find_mode(&info->var, &ddr_line_length, &xdr_line_length); | 626 | mode = ps3fb_find_mode(&info->var, &ddr_line_length, &xdr_line_length); |
623 | if (!mode) | 627 | if (!mode) |
624 | return -EINVAL; | 628 | return -EINVAL; |
625 | 629 | ||
626 | vmode = ps3fb_native_vmode(mode & PS3AV_MODE_MASK); | 630 | vmode = ps3fb_native_vmode(mode & PS3AV_MODE_MASK); |
627 | 631 | ||
628 | info->fix.xpanstep = info->var.xres_virtual > info->var.xres ? 1 : 0; | 632 | info->fix.xpanstep = info->var.xres_virtual > info->var.xres ? 1 : 0; |
629 | info->fix.ypanstep = info->var.yres_virtual > info->var.yres ? 1 : 0; | 633 | info->fix.ypanstep = info->var.yres_virtual > info->var.yres ? 1 : 0; |
630 | info->fix.line_length = xdr_line_length; | 634 | info->fix.line_length = xdr_line_length; |
631 | 635 | ||
632 | par->ddr_line_length = ddr_line_length; | 636 | par->ddr_line_length = ddr_line_length; |
633 | par->ddr_frame_size = vmode->yres * ddr_line_length; | 637 | par->ddr_frame_size = vmode->yres * ddr_line_length; |
634 | par->xdr_frame_size = info->var.yres_virtual * xdr_line_length; | 638 | par->xdr_frame_size = info->var.yres_virtual * xdr_line_length; |
635 | 639 | ||
636 | par->num_frames = info->fix.smem_len / | 640 | par->num_frames = info->fix.smem_len / |
637 | max(par->ddr_frame_size, par->xdr_frame_size); | 641 | max(par->ddr_frame_size, par->xdr_frame_size); |
638 | 642 | ||
639 | /* Keep the special bits we cannot set using fb_var_screeninfo */ | 643 | /* Keep the special bits we cannot set using fb_var_screeninfo */ |
640 | par->new_mode_id = (par->new_mode_id & ~PS3AV_MODE_MASK) | mode; | 644 | par->new_mode_id = (par->new_mode_id & ~PS3AV_MODE_MASK) | mode; |
641 | 645 | ||
642 | par->width = info->var.xres; | 646 | par->width = info->var.xres; |
643 | par->height = info->var.yres; | 647 | par->height = info->var.yres; |
644 | 648 | ||
645 | /* Start of the virtual frame buffer (relative to fullscreen) */ | 649 | /* Start of the virtual frame buffer (relative to fullscreen) */ |
646 | ddr_xoff = info->var.left_margin - vmode->left_margin; | 650 | ddr_xoff = info->var.left_margin - vmode->left_margin; |
647 | ddr_yoff = info->var.upper_margin - vmode->upper_margin; | 651 | ddr_yoff = info->var.upper_margin - vmode->upper_margin; |
648 | offset = ddr_yoff * ddr_line_length + ddr_xoff * BPP; | 652 | offset = ddr_yoff * ddr_line_length + ddr_xoff * BPP; |
649 | 653 | ||
650 | par->fb_offset = GPU_ALIGN_UP(offset); | 654 | par->fb_offset = GPU_ALIGN_UP(offset); |
651 | par->full_offset = par->fb_offset - offset; | 655 | par->full_offset = par->fb_offset - offset; |
652 | par->pan_offset = info->var.yoffset * xdr_line_length + | 656 | par->pan_offset = info->var.yoffset * xdr_line_length + |
653 | info->var.xoffset * BPP; | 657 | info->var.xoffset * BPP; |
654 | 658 | ||
655 | if (par->new_mode_id != par->mode_id) { | 659 | if (par->new_mode_id != par->mode_id) { |
656 | if (ps3av_set_video_mode(par->new_mode_id)) { | 660 | if (ps3av_set_video_mode(par->new_mode_id)) { |
657 | par->new_mode_id = par->mode_id; | 661 | par->new_mode_id = par->mode_id; |
658 | return -EINVAL; | 662 | return -EINVAL; |
659 | } | 663 | } |
660 | par->mode_id = par->new_mode_id; | 664 | par->mode_id = par->new_mode_id; |
661 | } | 665 | } |
662 | 666 | ||
663 | /* Clear XDR frame buffer memory */ | 667 | /* Clear XDR frame buffer memory */ |
664 | memset((void __force *)info->screen_base, 0, info->fix.smem_len); | 668 | memset((void __force *)info->screen_base, 0, info->fix.smem_len); |
665 | 669 | ||
666 | /* Clear DDR frame buffer memory */ | 670 | /* Clear DDR frame buffer memory */ |
667 | lines = vmode->yres * par->num_frames; | 671 | lines = vmode->yres * par->num_frames; |
668 | if (par->full_offset) | 672 | if (par->full_offset) |
669 | lines++; | 673 | lines++; |
670 | maxlines = info->fix.smem_len / ddr_line_length; | 674 | maxlines = info->fix.smem_len / ddr_line_length; |
671 | for (dst = 0; lines; dst += maxlines * ddr_line_length) { | 675 | for (dst = 0; lines; dst += maxlines * ddr_line_length) { |
672 | unsigned int l = min(lines, maxlines); | 676 | unsigned int l = min(lines, maxlines); |
673 | ps3fb_sync_image(info->device, 0, dst, 0, vmode->xres, l, | 677 | ps3fb_sync_image(info->device, 0, dst, 0, vmode->xres, l, |
674 | ddr_line_length, ddr_line_length); | 678 | ddr_line_length, ddr_line_length); |
675 | lines -= l; | 679 | lines -= l; |
676 | } | 680 | } |
677 | 681 | ||
678 | return 0; | 682 | return 0; |
679 | } | 683 | } |
680 | 684 | ||
681 | /* | 685 | /* |
682 | * Set a single color register. The values supplied are already | 686 | * Set a single color register. The values supplied are already |
683 | * rounded down to the hardware's capabilities (according to the | 687 | * rounded down to the hardware's capabilities (according to the |
684 | * entries in the var structure). Return != 0 for invalid regno. | 688 | * entries in the var structure). Return != 0 for invalid regno. |
685 | */ | 689 | */ |
686 | 690 | ||
687 | static int ps3fb_setcolreg(unsigned int regno, unsigned int red, | 691 | static int ps3fb_setcolreg(unsigned int regno, unsigned int red, |
688 | unsigned int green, unsigned int blue, | 692 | unsigned int green, unsigned int blue, |
689 | unsigned int transp, struct fb_info *info) | 693 | unsigned int transp, struct fb_info *info) |
690 | { | 694 | { |
691 | if (regno >= 16) | 695 | if (regno >= 16) |
692 | return 1; | 696 | return 1; |
693 | 697 | ||
694 | red >>= 8; | 698 | red >>= 8; |
695 | green >>= 8; | 699 | green >>= 8; |
696 | blue >>= 8; | 700 | blue >>= 8; |
697 | transp >>= 8; | 701 | transp >>= 8; |
698 | 702 | ||
699 | ((u32 *)info->pseudo_palette)[regno] = transp << 24 | red << 16 | | 703 | ((u32 *)info->pseudo_palette)[regno] = transp << 24 | red << 16 | |
700 | green << 8 | blue; | 704 | green << 8 | blue; |
701 | return 0; | 705 | return 0; |
702 | } | 706 | } |
703 | 707 | ||
704 | static int ps3fb_pan_display(struct fb_var_screeninfo *var, | 708 | static int ps3fb_pan_display(struct fb_var_screeninfo *var, |
705 | struct fb_info *info) | 709 | struct fb_info *info) |
706 | { | 710 | { |
707 | struct ps3fb_par *par = info->par; | 711 | struct ps3fb_par *par = info->par; |
708 | 712 | ||
709 | par->pan_offset = var->yoffset * info->fix.line_length + | 713 | par->pan_offset = var->yoffset * info->fix.line_length + |
710 | var->xoffset * BPP; | 714 | var->xoffset * BPP; |
711 | return 0; | 715 | return 0; |
712 | } | 716 | } |
713 | 717 | ||
714 | /* | 718 | /* |
715 | * As we have a virtual frame buffer, we need our own mmap function | 719 | * As we have a virtual frame buffer, we need our own mmap function |
716 | */ | 720 | */ |
717 | 721 | ||
718 | static int ps3fb_mmap(struct fb_info *info, struct vm_area_struct *vma) | 722 | static int ps3fb_mmap(struct fb_info *info, struct vm_area_struct *vma) |
719 | { | 723 | { |
720 | unsigned long size, offset; | 724 | unsigned long size, offset; |
721 | 725 | ||
722 | size = vma->vm_end - vma->vm_start; | 726 | size = vma->vm_end - vma->vm_start; |
723 | offset = vma->vm_pgoff << PAGE_SHIFT; | 727 | offset = vma->vm_pgoff << PAGE_SHIFT; |
724 | if (offset + size > info->fix.smem_len) | 728 | if (offset + size > info->fix.smem_len) |
725 | return -EINVAL; | 729 | return -EINVAL; |
726 | 730 | ||
727 | offset += info->fix.smem_start; | 731 | offset += info->fix.smem_start; |
728 | if (remap_pfn_range(vma, vma->vm_start, offset >> PAGE_SHIFT, | 732 | if (remap_pfn_range(vma, vma->vm_start, offset >> PAGE_SHIFT, |
729 | size, vma->vm_page_prot)) | 733 | size, vma->vm_page_prot)) |
730 | return -EAGAIN; | 734 | return -EAGAIN; |
731 | 735 | ||
732 | dev_dbg(info->device, "ps3fb: mmap framebuffer P(%lx)->V(%lx)\n", | 736 | dev_dbg(info->device, "ps3fb: mmap framebuffer P(%lx)->V(%lx)\n", |
733 | offset, vma->vm_start); | 737 | offset, vma->vm_start); |
734 | return 0; | 738 | return 0; |
735 | } | 739 | } |
736 | 740 | ||
737 | /* | 741 | /* |
738 | * Blank the display | 742 | * Blank the display |
739 | */ | 743 | */ |
740 | 744 | ||
741 | static int ps3fb_blank(int blank, struct fb_info *info) | 745 | static int ps3fb_blank(int blank, struct fb_info *info) |
742 | { | 746 | { |
743 | int retval; | 747 | int retval; |
744 | 748 | ||
745 | dev_dbg(info->device, "%s: blank:%d\n", __func__, blank); | 749 | dev_dbg(info->device, "%s: blank:%d\n", __func__, blank); |
746 | switch (blank) { | 750 | switch (blank) { |
747 | case FB_BLANK_POWERDOWN: | 751 | case FB_BLANK_POWERDOWN: |
748 | case FB_BLANK_HSYNC_SUSPEND: | 752 | case FB_BLANK_HSYNC_SUSPEND: |
749 | case FB_BLANK_VSYNC_SUSPEND: | 753 | case FB_BLANK_VSYNC_SUSPEND: |
750 | case FB_BLANK_NORMAL: | 754 | case FB_BLANK_NORMAL: |
751 | retval = ps3av_video_mute(1); /* mute on */ | 755 | retval = ps3av_video_mute(1); /* mute on */ |
752 | if (!retval) | 756 | if (!retval) |
753 | ps3fb.is_blanked = 1; | 757 | ps3fb.is_blanked = 1; |
754 | break; | 758 | break; |
755 | 759 | ||
756 | default: /* unblank */ | 760 | default: /* unblank */ |
757 | retval = ps3av_video_mute(0); /* mute off */ | 761 | retval = ps3av_video_mute(0); /* mute off */ |
758 | if (!retval) | 762 | if (!retval) |
759 | ps3fb.is_blanked = 0; | 763 | ps3fb.is_blanked = 0; |
760 | break; | 764 | break; |
761 | } | 765 | } |
762 | return retval; | 766 | return retval; |
763 | } | 767 | } |
764 | 768 | ||
765 | static int ps3fb_get_vblank(struct fb_vblank *vblank) | 769 | static int ps3fb_get_vblank(struct fb_vblank *vblank) |
766 | { | 770 | { |
767 | memset(vblank, 0, sizeof(*vblank)); | 771 | memset(vblank, 0, sizeof(*vblank)); |
768 | vblank->flags = FB_VBLANK_HAVE_VSYNC; | 772 | vblank->flags = FB_VBLANK_HAVE_VSYNC; |
769 | return 0; | 773 | return 0; |
770 | } | 774 | } |
771 | 775 | ||
772 | static int ps3fb_wait_for_vsync(u32 crtc) | 776 | static int ps3fb_wait_for_vsync(u32 crtc) |
773 | { | 777 | { |
774 | int ret; | 778 | int ret; |
775 | u64 count; | 779 | u64 count; |
776 | 780 | ||
777 | count = ps3fb.vblank_count; | 781 | count = ps3fb.vblank_count; |
778 | ret = wait_event_interruptible_timeout(ps3fb.wait_vsync, | 782 | ret = wait_event_interruptible_timeout(ps3fb.wait_vsync, |
779 | count != ps3fb.vblank_count, | 783 | count != ps3fb.vblank_count, |
780 | HZ / 10); | 784 | HZ / 10); |
781 | if (!ret) | 785 | if (!ret) |
782 | return -ETIMEDOUT; | 786 | return -ETIMEDOUT; |
783 | 787 | ||
784 | return 0; | 788 | return 0; |
785 | } | 789 | } |
786 | 790 | ||
787 | static void ps3fb_flip_ctl(int on, void *data) | ||
788 | { | ||
789 | struct ps3fb_priv *priv = data; | ||
790 | if (on) | ||
791 | atomic_dec_if_positive(&priv->ext_flip); | ||
792 | else | ||
793 | atomic_inc(&priv->ext_flip); | ||
794 | } | ||
795 | 791 | ||
796 | |||
797 | /* | 792 | /* |
798 | * ioctl | 793 | * ioctl |
799 | */ | 794 | */ |
800 | 795 | ||
801 | static int ps3fb_ioctl(struct fb_info *info, unsigned int cmd, | 796 | static int ps3fb_ioctl(struct fb_info *info, unsigned int cmd, |
802 | unsigned long arg) | 797 | unsigned long arg) |
803 | { | 798 | { |
804 | void __user *argp = (void __user *)arg; | 799 | void __user *argp = (void __user *)arg; |
805 | u32 val; | 800 | u32 val; |
806 | int retval = -EFAULT; | 801 | int retval = -EFAULT; |
807 | 802 | ||
808 | switch (cmd) { | 803 | switch (cmd) { |
809 | case FBIOGET_VBLANK: | 804 | case FBIOGET_VBLANK: |
810 | { | 805 | { |
811 | struct fb_vblank vblank; | 806 | struct fb_vblank vblank; |
812 | dev_dbg(info->device, "FBIOGET_VBLANK:\n"); | 807 | dev_dbg(info->device, "FBIOGET_VBLANK:\n"); |
813 | retval = ps3fb_get_vblank(&vblank); | 808 | retval = ps3fb_get_vblank(&vblank); |
814 | if (retval) | 809 | if (retval) |
815 | break; | 810 | break; |
816 | 811 | ||
817 | if (copy_to_user(argp, &vblank, sizeof(vblank))) | 812 | if (copy_to_user(argp, &vblank, sizeof(vblank))) |
818 | retval = -EFAULT; | 813 | retval = -EFAULT; |
819 | break; | 814 | break; |
820 | } | 815 | } |
821 | 816 | ||
822 | case FBIO_WAITFORVSYNC: | 817 | case FBIO_WAITFORVSYNC: |
823 | { | 818 | { |
824 | u32 crt; | 819 | u32 crt; |
825 | dev_dbg(info->device, "FBIO_WAITFORVSYNC:\n"); | 820 | dev_dbg(info->device, "FBIO_WAITFORVSYNC:\n"); |
826 | if (get_user(crt, (u32 __user *) arg)) | 821 | if (get_user(crt, (u32 __user *) arg)) |
827 | break; | 822 | break; |
828 | 823 | ||
829 | retval = ps3fb_wait_for_vsync(crt); | 824 | retval = ps3fb_wait_for_vsync(crt); |
830 | break; | 825 | break; |
831 | } | 826 | } |
832 | 827 | ||
833 | case PS3FB_IOCTL_SETMODE: | 828 | case PS3FB_IOCTL_SETMODE: |
834 | { | 829 | { |
835 | struct ps3fb_par *par = info->par; | 830 | struct ps3fb_par *par = info->par; |
836 | const struct fb_videomode *vmode; | 831 | const struct fb_videomode *vmode; |
837 | struct fb_var_screeninfo var; | 832 | struct fb_var_screeninfo var; |
838 | 833 | ||
839 | if (copy_from_user(&val, argp, sizeof(val))) | 834 | if (copy_from_user(&val, argp, sizeof(val))) |
840 | break; | 835 | break; |
841 | 836 | ||
842 | if (!(val & PS3AV_MODE_MASK)) { | 837 | if (!(val & PS3AV_MODE_MASK)) { |
843 | u32 id = ps3av_get_auto_mode(); | 838 | u32 id = ps3av_get_auto_mode(); |
844 | if (id > 0) | 839 | if (id > 0) |
845 | val = (val & ~PS3AV_MODE_MASK) | id; | 840 | val = (val & ~PS3AV_MODE_MASK) | id; |
846 | } | 841 | } |
847 | dev_dbg(info->device, "PS3FB_IOCTL_SETMODE:%x\n", val); | 842 | dev_dbg(info->device, "PS3FB_IOCTL_SETMODE:%x\n", val); |
848 | retval = -EINVAL; | 843 | retval = -EINVAL; |
849 | vmode = ps3fb_vmode(val); | 844 | vmode = ps3fb_vmode(val); |
850 | if (vmode) { | 845 | if (vmode) { |
851 | var = info->var; | 846 | var = info->var; |
852 | fb_videomode_to_var(&var, vmode); | 847 | fb_videomode_to_var(&var, vmode); |
853 | acquire_console_sem(); | 848 | acquire_console_sem(); |
854 | info->flags |= FBINFO_MISC_USEREVENT; | 849 | info->flags |= FBINFO_MISC_USEREVENT; |
855 | /* Force, in case only special bits changed */ | 850 | /* Force, in case only special bits changed */ |
856 | var.activate |= FB_ACTIVATE_FORCE; | 851 | var.activate |= FB_ACTIVATE_FORCE; |
857 | par->new_mode_id = val; | 852 | par->new_mode_id = val; |
858 | retval = fb_set_var(info, &var); | 853 | retval = fb_set_var(info, &var); |
859 | info->flags &= ~FBINFO_MISC_USEREVENT; | 854 | info->flags &= ~FBINFO_MISC_USEREVENT; |
860 | release_console_sem(); | 855 | release_console_sem(); |
861 | } | 856 | } |
862 | break; | 857 | break; |
863 | } | 858 | } |
864 | 859 | ||
865 | case PS3FB_IOCTL_GETMODE: | 860 | case PS3FB_IOCTL_GETMODE: |
866 | val = ps3av_get_mode(); | 861 | val = ps3av_get_mode(); |
867 | dev_dbg(info->device, "PS3FB_IOCTL_GETMODE:%x\n", val); | 862 | dev_dbg(info->device, "PS3FB_IOCTL_GETMODE:%x\n", val); |
868 | if (!copy_to_user(argp, &val, sizeof(val))) | 863 | if (!copy_to_user(argp, &val, sizeof(val))) |
869 | retval = 0; | 864 | retval = 0; |
870 | break; | 865 | break; |
871 | 866 | ||
872 | case PS3FB_IOCTL_SCREENINFO: | 867 | case PS3FB_IOCTL_SCREENINFO: |
873 | { | 868 | { |
874 | struct ps3fb_par *par = info->par; | 869 | struct ps3fb_par *par = info->par; |
875 | struct ps3fb_ioctl_res res; | 870 | struct ps3fb_ioctl_res res; |
876 | dev_dbg(info->device, "PS3FB_IOCTL_SCREENINFO:\n"); | 871 | dev_dbg(info->device, "PS3FB_IOCTL_SCREENINFO:\n"); |
877 | res.xres = info->fix.line_length / BPP; | 872 | res.xres = info->fix.line_length / BPP; |
878 | res.yres = info->var.yres_virtual; | 873 | res.yres = info->var.yres_virtual; |
879 | res.xoff = (res.xres - info->var.xres) / 2; | 874 | res.xoff = (res.xres - info->var.xres) / 2; |
880 | res.yoff = (res.yres - info->var.yres) / 2; | 875 | res.yoff = (res.yres - info->var.yres) / 2; |
881 | res.num_frames = par->num_frames; | 876 | res.num_frames = par->num_frames; |
882 | if (!copy_to_user(argp, &res, sizeof(res))) | 877 | if (!copy_to_user(argp, &res, sizeof(res))) |
883 | retval = 0; | 878 | retval = 0; |
884 | break; | 879 | break; |
885 | } | 880 | } |
886 | 881 | ||
887 | case PS3FB_IOCTL_ON: | 882 | case PS3FB_IOCTL_ON: |
888 | dev_dbg(info->device, "PS3FB_IOCTL_ON:\n"); | 883 | dev_dbg(info->device, "PS3FB_IOCTL_ON:\n"); |
889 | atomic_inc(&ps3fb.ext_flip); | 884 | atomic_inc(&ps3fb.ext_flip); |
890 | retval = 0; | 885 | retval = 0; |
891 | break; | 886 | break; |
892 | 887 | ||
893 | case PS3FB_IOCTL_OFF: | 888 | case PS3FB_IOCTL_OFF: |
894 | dev_dbg(info->device, "PS3FB_IOCTL_OFF:\n"); | 889 | dev_dbg(info->device, "PS3FB_IOCTL_OFF:\n"); |
895 | atomic_dec_if_positive(&ps3fb.ext_flip); | 890 | atomic_dec_if_positive(&ps3fb.ext_flip); |
896 | retval = 0; | 891 | retval = 0; |
897 | break; | 892 | break; |
898 | 893 | ||
899 | case PS3FB_IOCTL_FSEL: | 894 | case PS3FB_IOCTL_FSEL: |
900 | if (copy_from_user(&val, argp, sizeof(val))) | 895 | if (copy_from_user(&val, argp, sizeof(val))) |
901 | break; | 896 | break; |
902 | 897 | ||
903 | dev_dbg(info->device, "PS3FB_IOCTL_FSEL:%d\n", val); | 898 | dev_dbg(info->device, "PS3FB_IOCTL_FSEL:%d\n", val); |
904 | acquire_console_sem(); | 899 | acquire_console_sem(); |
905 | retval = ps3fb_sync(info, val); | 900 | retval = ps3fb_sync(info, val); |
906 | release_console_sem(); | 901 | release_console_sem(); |
907 | break; | 902 | break; |
908 | 903 | ||
909 | default: | 904 | default: |
910 | retval = -ENOIOCTLCMD; | 905 | retval = -ENOIOCTLCMD; |
911 | break; | 906 | break; |
912 | } | 907 | } |
913 | return retval; | 908 | return retval; |
914 | } | 909 | } |
915 | 910 | ||
916 | static int ps3fbd(void *arg) | 911 | static int ps3fbd(void *arg) |
917 | { | 912 | { |
918 | struct fb_info *info = arg; | 913 | struct fb_info *info = arg; |
919 | 914 | ||
920 | set_freezable(); | 915 | set_freezable(); |
921 | while (!kthread_should_stop()) { | 916 | while (!kthread_should_stop()) { |
922 | try_to_freeze(); | 917 | try_to_freeze(); |
923 | set_current_state(TASK_INTERRUPTIBLE); | 918 | set_current_state(TASK_INTERRUPTIBLE); |
924 | if (ps3fb.is_kicked) { | 919 | if (ps3fb.is_kicked) { |
925 | ps3fb.is_kicked = 0; | 920 | ps3fb.is_kicked = 0; |
926 | acquire_console_sem(); | 921 | acquire_console_sem(); |
927 | ps3fb_sync(info, 0); /* single buffer */ | 922 | ps3fb_sync(info, 0); /* single buffer */ |
928 | release_console_sem(); | 923 | release_console_sem(); |
929 | } | 924 | } |
930 | schedule(); | 925 | schedule(); |
931 | } | 926 | } |
932 | return 0; | 927 | return 0; |
933 | } | 928 | } |
934 | 929 | ||
935 | static irqreturn_t ps3fb_vsync_interrupt(int irq, void *ptr) | 930 | static irqreturn_t ps3fb_vsync_interrupt(int irq, void *ptr) |
936 | { | 931 | { |
937 | struct device *dev = ptr; | 932 | struct device *dev = ptr; |
938 | u64 v1; | 933 | u64 v1; |
939 | int status; | 934 | int status; |
940 | struct display_head *head = &ps3fb.dinfo->display_head[1]; | 935 | struct display_head *head = &ps3fb.dinfo->display_head[1]; |
941 | 936 | ||
942 | status = lv1_gpu_context_intr(ps3fb.context_handle, &v1); | 937 | status = lv1_gpu_context_intr(ps3fb.context_handle, &v1); |
943 | if (status) { | 938 | if (status) { |
944 | dev_err(dev, "%s: lv1_gpu_context_intr failed: %d\n", __func__, | 939 | dev_err(dev, "%s: lv1_gpu_context_intr failed: %d\n", __func__, |
945 | status); | 940 | status); |
946 | return IRQ_NONE; | 941 | return IRQ_NONE; |
947 | } | 942 | } |
948 | 943 | ||
949 | if (v1 & (1 << GPU_INTR_STATUS_VSYNC_1)) { | 944 | if (v1 & (1 << GPU_INTR_STATUS_VSYNC_1)) { |
950 | /* VSYNC */ | 945 | /* VSYNC */ |
951 | ps3fb.vblank_count = head->vblank_count; | 946 | ps3fb.vblank_count = head->vblank_count; |
952 | if (ps3fb.task && !ps3fb.is_blanked && | 947 | if (ps3fb.task && !ps3fb.is_blanked && |
953 | !atomic_read(&ps3fb.ext_flip)) { | 948 | !atomic_read(&ps3fb.ext_flip)) { |
954 | ps3fb.is_kicked = 1; | 949 | ps3fb.is_kicked = 1; |
955 | wake_up_process(ps3fb.task); | 950 | wake_up_process(ps3fb.task); |
956 | } | 951 | } |
957 | wake_up_interruptible(&ps3fb.wait_vsync); | 952 | wake_up_interruptible(&ps3fb.wait_vsync); |
958 | } | 953 | } |
959 | 954 | ||
960 | return IRQ_HANDLED; | 955 | return IRQ_HANDLED; |
961 | } | 956 | } |
962 | 957 | ||
963 | 958 | ||
964 | static int ps3fb_vsync_settings(struct gpu_driver_info *dinfo, | 959 | static int ps3fb_vsync_settings(struct gpu_driver_info *dinfo, |
965 | struct device *dev) | 960 | struct device *dev) |
966 | { | 961 | { |
967 | int error; | 962 | int error; |
968 | 963 | ||
969 | dev_dbg(dev, "version_driver:%x\n", dinfo->version_driver); | 964 | dev_dbg(dev, "version_driver:%x\n", dinfo->version_driver); |
970 | dev_dbg(dev, "irq outlet:%x\n", dinfo->irq.irq_outlet); | 965 | dev_dbg(dev, "irq outlet:%x\n", dinfo->irq.irq_outlet); |
971 | dev_dbg(dev, | 966 | dev_dbg(dev, |
972 | "version_gpu: %x memory_size: %x ch: %x core_freq: %d " | 967 | "version_gpu: %x memory_size: %x ch: %x core_freq: %d " |
973 | "mem_freq:%d\n", | 968 | "mem_freq:%d\n", |
974 | dinfo->version_gpu, dinfo->memory_size, dinfo->hardware_channel, | 969 | dinfo->version_gpu, dinfo->memory_size, dinfo->hardware_channel, |
975 | dinfo->nvcore_frequency/1000000, dinfo->memory_frequency/1000000); | 970 | dinfo->nvcore_frequency/1000000, dinfo->memory_frequency/1000000); |
976 | 971 | ||
977 | if (dinfo->version_driver != GPU_DRIVER_INFO_VERSION) { | 972 | if (dinfo->version_driver != GPU_DRIVER_INFO_VERSION) { |
978 | dev_err(dev, "%s: version_driver err:%x\n", __func__, | 973 | dev_err(dev, "%s: version_driver err:%x\n", __func__, |
979 | dinfo->version_driver); | 974 | dinfo->version_driver); |
980 | return -EINVAL; | 975 | return -EINVAL; |
981 | } | 976 | } |
982 | 977 | ||
983 | error = ps3_irq_plug_setup(PS3_BINDING_CPU_ANY, dinfo->irq.irq_outlet, | 978 | error = ps3_irq_plug_setup(PS3_BINDING_CPU_ANY, dinfo->irq.irq_outlet, |
984 | &ps3fb.irq_no); | 979 | &ps3fb.irq_no); |
985 | if (error) { | 980 | if (error) { |
986 | dev_err(dev, "%s: ps3_alloc_irq failed %d\n", __func__, error); | 981 | dev_err(dev, "%s: ps3_alloc_irq failed %d\n", __func__, error); |
987 | return error; | 982 | return error; |
988 | } | 983 | } |
989 | 984 | ||
990 | error = request_irq(ps3fb.irq_no, ps3fb_vsync_interrupt, IRQF_DISABLED, | 985 | error = request_irq(ps3fb.irq_no, ps3fb_vsync_interrupt, IRQF_DISABLED, |
991 | DEVICE_NAME, dev); | 986 | DEVICE_NAME, dev); |
992 | if (error) { | 987 | if (error) { |
993 | dev_err(dev, "%s: request_irq failed %d\n", __func__, error); | 988 | dev_err(dev, "%s: request_irq failed %d\n", __func__, error); |
994 | ps3_irq_plug_destroy(ps3fb.irq_no); | 989 | ps3_irq_plug_destroy(ps3fb.irq_no); |
995 | return error; | 990 | return error; |
996 | } | 991 | } |
997 | 992 | ||
998 | dinfo->irq.mask = (1 << GPU_INTR_STATUS_VSYNC_1) | | 993 | dinfo->irq.mask = (1 << GPU_INTR_STATUS_VSYNC_1) | |
999 | (1 << GPU_INTR_STATUS_FLIP_1); | 994 | (1 << GPU_INTR_STATUS_FLIP_1); |
1000 | return 0; | 995 | return 0; |
1001 | } | 996 | } |
1002 | 997 | ||
1003 | static int ps3fb_xdr_settings(u64 xdr_lpar, struct device *dev) | 998 | static int ps3fb_xdr_settings(u64 xdr_lpar, struct device *dev) |
1004 | { | 999 | { |
1005 | int status; | 1000 | int status; |
1006 | 1001 | ||
1007 | status = lv1_gpu_context_iomap(ps3fb.context_handle, GPU_IOIF, | 1002 | status = lv1_gpu_context_iomap(ps3fb.context_handle, GPU_IOIF, |
1008 | xdr_lpar, ps3fb_videomemory.size, 0); | 1003 | xdr_lpar, ps3fb_videomemory.size, 0); |
1009 | if (status) { | 1004 | if (status) { |
1010 | dev_err(dev, "%s: lv1_gpu_context_iomap failed: %d\n", | 1005 | dev_err(dev, "%s: lv1_gpu_context_iomap failed: %d\n", |
1011 | __func__, status); | 1006 | __func__, status); |
1012 | return -ENXIO; | 1007 | return -ENXIO; |
1013 | } | 1008 | } |
1014 | dev_dbg(dev, "video:%p ioif:%lx lpar:%lx size:%lx\n", | 1009 | dev_dbg(dev, "video:%p ioif:%lx lpar:%lx size:%lx\n", |
1015 | ps3fb_videomemory.address, GPU_IOIF, xdr_lpar, | 1010 | ps3fb_videomemory.address, GPU_IOIF, xdr_lpar, |
1016 | ps3fb_videomemory.size); | 1011 | ps3fb_videomemory.size); |
1017 | 1012 | ||
1018 | status = lv1_gpu_context_attribute(ps3fb.context_handle, | 1013 | status = lv1_gpu_context_attribute(ps3fb.context_handle, |
1019 | L1GPU_CONTEXT_ATTRIBUTE_FB_SETUP, | 1014 | L1GPU_CONTEXT_ATTRIBUTE_FB_SETUP, |
1020 | xdr_lpar, GPU_CMD_BUF_SIZE, | 1015 | xdr_lpar, GPU_CMD_BUF_SIZE, |
1021 | GPU_IOIF, 0); | 1016 | GPU_IOIF, 0); |
1022 | if (status) { | 1017 | if (status) { |
1023 | dev_err(dev, | 1018 | dev_err(dev, |
1024 | "%s: lv1_gpu_context_attribute FB_SETUP failed: %d\n", | 1019 | "%s: lv1_gpu_context_attribute FB_SETUP failed: %d\n", |
1025 | __func__, status); | 1020 | __func__, status); |
1026 | return -ENXIO; | 1021 | return -ENXIO; |
1027 | } | 1022 | } |
1028 | return 0; | 1023 | return 0; |
1029 | } | 1024 | } |
1030 | 1025 | ||
1031 | static struct fb_ops ps3fb_ops = { | 1026 | static struct fb_ops ps3fb_ops = { |
1032 | .fb_open = ps3fb_open, | 1027 | .fb_open = ps3fb_open, |
1033 | .fb_release = ps3fb_release, | 1028 | .fb_release = ps3fb_release, |
1034 | .fb_read = fb_sys_read, | 1029 | .fb_read = fb_sys_read, |
1035 | .fb_write = fb_sys_write, | 1030 | .fb_write = fb_sys_write, |
1036 | .fb_check_var = ps3fb_check_var, | 1031 | .fb_check_var = ps3fb_check_var, |
1037 | .fb_set_par = ps3fb_set_par, | 1032 | .fb_set_par = ps3fb_set_par, |
1038 | .fb_setcolreg = ps3fb_setcolreg, | 1033 | .fb_setcolreg = ps3fb_setcolreg, |
1039 | .fb_pan_display = ps3fb_pan_display, | 1034 | .fb_pan_display = ps3fb_pan_display, |
1040 | .fb_fillrect = sys_fillrect, | 1035 | .fb_fillrect = sys_fillrect, |
1041 | .fb_copyarea = sys_copyarea, | 1036 | .fb_copyarea = sys_copyarea, |
1042 | .fb_imageblit = sys_imageblit, | 1037 | .fb_imageblit = sys_imageblit, |
1043 | .fb_mmap = ps3fb_mmap, | 1038 | .fb_mmap = ps3fb_mmap, |
1044 | .fb_blank = ps3fb_blank, | 1039 | .fb_blank = ps3fb_blank, |
1045 | .fb_ioctl = ps3fb_ioctl, | 1040 | .fb_ioctl = ps3fb_ioctl, |
1046 | .fb_compat_ioctl = ps3fb_ioctl | 1041 | .fb_compat_ioctl = ps3fb_ioctl |
1047 | }; | 1042 | }; |
1048 | 1043 | ||
1049 | static struct fb_fix_screeninfo ps3fb_fix __initdata = { | 1044 | static struct fb_fix_screeninfo ps3fb_fix __initdata = { |
1050 | .id = DEVICE_NAME, | 1045 | .id = DEVICE_NAME, |
1051 | .type = FB_TYPE_PACKED_PIXELS, | 1046 | .type = FB_TYPE_PACKED_PIXELS, |
1052 | .visual = FB_VISUAL_TRUECOLOR, | 1047 | .visual = FB_VISUAL_TRUECOLOR, |
1053 | .accel = FB_ACCEL_NONE, | 1048 | .accel = FB_ACCEL_NONE, |
1054 | }; | 1049 | }; |
1055 | 1050 | ||
1056 | static int ps3fb_set_sync(struct device *dev) | 1051 | static int ps3fb_set_sync(struct device *dev) |
1057 | { | 1052 | { |
1058 | int status; | 1053 | int status; |
1059 | 1054 | ||
1060 | #ifdef HEAD_A | 1055 | #ifdef HEAD_A |
1061 | status = lv1_gpu_context_attribute(0x0, | 1056 | status = lv1_gpu_context_attribute(0x0, |
1062 | L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC, | 1057 | L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC, |
1063 | 0, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0); | 1058 | 0, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0); |
1064 | if (status) { | 1059 | if (status) { |
1065 | dev_err(dev, | 1060 | dev_err(dev, |
1066 | "%s: lv1_gpu_context_attribute DISPLAY_SYNC failed: " | 1061 | "%s: lv1_gpu_context_attribute DISPLAY_SYNC failed: " |
1067 | "%d\n", | 1062 | "%d\n", |
1068 | __func__, status); | 1063 | __func__, status); |
1069 | return -1; | 1064 | return -1; |
1070 | } | 1065 | } |
1071 | #endif | 1066 | #endif |
1072 | #ifdef HEAD_B | 1067 | #ifdef HEAD_B |
1073 | status = lv1_gpu_context_attribute(0x0, | 1068 | status = lv1_gpu_context_attribute(0x0, |
1074 | L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC, | 1069 | L1GPU_CONTEXT_ATTRIBUTE_DISPLAY_SYNC, |
1075 | 1, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0); | 1070 | 1, L1GPU_DISPLAY_SYNC_VSYNC, 0, 0); |
1076 | 1071 | ||
1077 | if (status) { | 1072 | if (status) { |
1078 | dev_err(dev, | 1073 | dev_err(dev, |
1079 | "%s: lv1_gpu_context_attribute DISPLAY_SYNC failed: " | 1074 | "%s: lv1_gpu_context_attribute DISPLAY_SYNC failed: " |
1080 | "%d\n", | 1075 | "%d\n", |
1081 | __func__, status); | 1076 | __func__, status); |
1082 | return -1; | 1077 | return -1; |
1083 | } | 1078 | } |
1084 | #endif | 1079 | #endif |
1085 | return 0; | 1080 | return 0; |
1086 | } | 1081 | } |
1087 | 1082 | ||
1088 | static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev) | 1083 | static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev) |
1089 | { | 1084 | { |
1090 | struct fb_info *info; | 1085 | struct fb_info *info; |
1091 | struct ps3fb_par *par; | 1086 | struct ps3fb_par *par; |
1092 | int retval = -ENOMEM; | 1087 | int retval = -ENOMEM; |
1093 | u64 ddr_lpar = 0; | 1088 | u64 ddr_lpar = 0; |
1094 | u64 lpar_dma_control = 0; | 1089 | u64 lpar_dma_control = 0; |
1095 | u64 lpar_driver_info = 0; | 1090 | u64 lpar_driver_info = 0; |
1096 | u64 lpar_reports = 0; | 1091 | u64 lpar_reports = 0; |
1097 | u64 lpar_reports_size = 0; | 1092 | u64 lpar_reports_size = 0; |
1098 | u64 xdr_lpar; | 1093 | u64 xdr_lpar; |
1099 | void *fb_start; | 1094 | void *fb_start; |
1100 | int status; | 1095 | int status; |
1101 | struct task_struct *task; | 1096 | struct task_struct *task; |
1102 | unsigned long max_ps3fb_size; | 1097 | unsigned long max_ps3fb_size; |
1103 | 1098 | ||
1104 | if (ps3fb_videomemory.size < GPU_CMD_BUF_SIZE) { | 1099 | if (ps3fb_videomemory.size < GPU_CMD_BUF_SIZE) { |
1105 | dev_err(&dev->core, "%s: Not enough video memory\n", __func__); | 1100 | dev_err(&dev->core, "%s: Not enough video memory\n", __func__); |
1106 | return -ENOMEM; | 1101 | return -ENOMEM; |
1107 | } | 1102 | } |
1108 | 1103 | ||
1109 | status = ps3_open_hv_device(dev); | 1104 | status = ps3_open_hv_device(dev); |
1110 | if (status) { | 1105 | if (status) { |
1111 | dev_err(&dev->core, "%s: ps3_open_hv_device failed\n", | 1106 | dev_err(&dev->core, "%s: ps3_open_hv_device failed\n", |
1112 | __func__); | 1107 | __func__); |
1113 | goto err; | 1108 | goto err; |
1114 | } | 1109 | } |
1115 | 1110 | ||
1116 | if (!ps3fb_mode) | 1111 | if (!ps3fb_mode) |
1117 | ps3fb_mode = ps3av_get_mode(); | 1112 | ps3fb_mode = ps3av_get_mode(); |
1118 | dev_dbg(&dev->core, "ps3fb_mode: %d\n", ps3fb_mode); | 1113 | dev_dbg(&dev->core, "ps3fb_mode: %d\n", ps3fb_mode); |
1119 | 1114 | ||
1120 | atomic_set(&ps3fb.f_count, -1); /* fbcon opens ps3fb */ | 1115 | atomic_set(&ps3fb.f_count, -1); /* fbcon opens ps3fb */ |
1121 | atomic_set(&ps3fb.ext_flip, 0); /* for flip with vsync */ | 1116 | atomic_set(&ps3fb.ext_flip, 0); /* for flip with vsync */ |
1122 | init_waitqueue_head(&ps3fb.wait_vsync); | 1117 | init_waitqueue_head(&ps3fb.wait_vsync); |
1123 | 1118 | ||
1124 | ps3fb_set_sync(&dev->core); | 1119 | ps3fb_set_sync(&dev->core); |
1125 | 1120 | ||
1126 | max_ps3fb_size = _ALIGN_UP(GPU_IOIF, 256*1024*1024) - GPU_IOIF; | 1121 | max_ps3fb_size = _ALIGN_UP(GPU_IOIF, 256*1024*1024) - GPU_IOIF; |
1127 | if (ps3fb_videomemory.size > max_ps3fb_size) { | 1122 | if (ps3fb_videomemory.size > max_ps3fb_size) { |
1128 | dev_info(&dev->core, "Limiting ps3fb mem size to %lu bytes\n", | 1123 | dev_info(&dev->core, "Limiting ps3fb mem size to %lu bytes\n", |
1129 | max_ps3fb_size); | 1124 | max_ps3fb_size); |
1130 | ps3fb_videomemory.size = max_ps3fb_size; | 1125 | ps3fb_videomemory.size = max_ps3fb_size; |
1131 | } | 1126 | } |
1132 | 1127 | ||
1133 | /* get gpu context handle */ | 1128 | /* get gpu context handle */ |
1134 | status = lv1_gpu_memory_allocate(ps3fb_videomemory.size, 0, 0, 0, 0, | 1129 | status = lv1_gpu_memory_allocate(ps3fb_videomemory.size, 0, 0, 0, 0, |
1135 | &ps3fb.memory_handle, &ddr_lpar); | 1130 | &ps3fb.memory_handle, &ddr_lpar); |
1136 | if (status) { | 1131 | if (status) { |
1137 | dev_err(&dev->core, "%s: lv1_gpu_memory_allocate failed: %d\n", | 1132 | dev_err(&dev->core, "%s: lv1_gpu_memory_allocate failed: %d\n", |
1138 | __func__, status); | 1133 | __func__, status); |
1139 | goto err; | 1134 | goto err; |
1140 | } | 1135 | } |
1141 | dev_dbg(&dev->core, "ddr:lpar:0x%lx\n", ddr_lpar); | 1136 | dev_dbg(&dev->core, "ddr:lpar:0x%lx\n", ddr_lpar); |
1142 | 1137 | ||
1143 | status = lv1_gpu_context_allocate(ps3fb.memory_handle, 0, | 1138 | status = lv1_gpu_context_allocate(ps3fb.memory_handle, 0, |
1144 | &ps3fb.context_handle, | 1139 | &ps3fb.context_handle, |
1145 | &lpar_dma_control, &lpar_driver_info, | 1140 | &lpar_dma_control, &lpar_driver_info, |
1146 | &lpar_reports, &lpar_reports_size); | 1141 | &lpar_reports, &lpar_reports_size); |
1147 | if (status) { | 1142 | if (status) { |
1148 | dev_err(&dev->core, | 1143 | dev_err(&dev->core, |
1149 | "%s: lv1_gpu_context_attribute failed: %d\n", __func__, | 1144 | "%s: lv1_gpu_context_attribute failed: %d\n", __func__, |
1150 | status); | 1145 | status); |
1151 | goto err_gpu_memory_free; | 1146 | goto err_gpu_memory_free; |
1152 | } | 1147 | } |
1153 | 1148 | ||
1154 | /* vsync interrupt */ | 1149 | /* vsync interrupt */ |
1155 | ps3fb.dinfo = (void __force *)ioremap(lpar_driver_info, 128 * 1024); | 1150 | ps3fb.dinfo = (void __force *)ioremap(lpar_driver_info, 128 * 1024); |
1156 | if (!ps3fb.dinfo) { | 1151 | if (!ps3fb.dinfo) { |
1157 | dev_err(&dev->core, "%s: ioremap failed\n", __func__); | 1152 | dev_err(&dev->core, "%s: ioremap failed\n", __func__); |
1158 | goto err_gpu_context_free; | 1153 | goto err_gpu_context_free; |
1159 | } | 1154 | } |
1160 | 1155 | ||
1161 | retval = ps3fb_vsync_settings(ps3fb.dinfo, &dev->core); | 1156 | retval = ps3fb_vsync_settings(ps3fb.dinfo, &dev->core); |
1162 | if (retval) | 1157 | if (retval) |
1163 | goto err_iounmap_dinfo; | 1158 | goto err_iounmap_dinfo; |
1164 | 1159 | ||
1165 | /* Clear memory to prevent kernel info leakage into userspace */ | 1160 | /* Clear memory to prevent kernel info leakage into userspace */ |
1166 | memset(ps3fb_videomemory.address, 0, ps3fb_videomemory.size); | 1161 | memset(ps3fb_videomemory.address, 0, ps3fb_videomemory.size); |
1167 | 1162 | ||
1168 | xdr_lpar = ps3_mm_phys_to_lpar(__pa(ps3fb_videomemory.address)); | 1163 | xdr_lpar = ps3_mm_phys_to_lpar(__pa(ps3fb_videomemory.address)); |
1169 | retval = ps3fb_xdr_settings(xdr_lpar, &dev->core); | 1164 | retval = ps3fb_xdr_settings(xdr_lpar, &dev->core); |
1170 | if (retval) | 1165 | if (retval) |
1171 | goto err_free_irq; | 1166 | goto err_free_irq; |
1172 | 1167 | ||
1173 | info = framebuffer_alloc(sizeof(struct ps3fb_par), &dev->core); | 1168 | info = framebuffer_alloc(sizeof(struct ps3fb_par), &dev->core); |
1174 | if (!info) | 1169 | if (!info) |
1175 | goto err_free_irq; | 1170 | goto err_free_irq; |
1176 | 1171 | ||
1177 | par = info->par; | 1172 | par = info->par; |
1178 | par->mode_id = ~ps3fb_mode; /* != ps3fb_mode, to trigger change */ | 1173 | par->mode_id = ~ps3fb_mode; /* != ps3fb_mode, to trigger change */ |
1179 | par->new_mode_id = ps3fb_mode; | 1174 | par->new_mode_id = ps3fb_mode; |
1180 | par->num_frames = 1; | 1175 | par->num_frames = 1; |
1181 | 1176 | ||
1182 | info->fbops = &ps3fb_ops; | 1177 | info->fbops = &ps3fb_ops; |
1183 | info->fix = ps3fb_fix; | 1178 | info->fix = ps3fb_fix; |
1184 | 1179 | ||
1185 | /* | 1180 | /* |
1186 | * The GPU command buffer is at the start of video memory | 1181 | * The GPU command buffer is at the start of video memory |
1187 | * As we don't use the full command buffer, we can put the actual | 1182 | * As we don't use the full command buffer, we can put the actual |
1188 | * frame buffer at offset GPU_FB_START and save some precious XDR | 1183 | * frame buffer at offset GPU_FB_START and save some precious XDR |
1189 | * memory | 1184 | * memory |
1190 | */ | 1185 | */ |
1191 | fb_start = ps3fb_videomemory.address + GPU_FB_START; | 1186 | fb_start = ps3fb_videomemory.address + GPU_FB_START; |
1192 | info->screen_base = (char __force __iomem *)fb_start; | 1187 | info->screen_base = (char __force __iomem *)fb_start; |
1193 | info->fix.smem_start = virt_to_abs(fb_start); | 1188 | info->fix.smem_start = virt_to_abs(fb_start); |
1194 | info->fix.smem_len = ps3fb_videomemory.size - GPU_FB_START; | 1189 | info->fix.smem_len = ps3fb_videomemory.size - GPU_FB_START; |
1195 | 1190 | ||
1196 | info->pseudo_palette = par->pseudo_palette; | 1191 | info->pseudo_palette = par->pseudo_palette; |
1197 | info->flags = FBINFO_DEFAULT | FBINFO_READS_FAST | | 1192 | info->flags = FBINFO_DEFAULT | FBINFO_READS_FAST | |
1198 | FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN; | 1193 | FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN; |
1199 | 1194 | ||
1200 | retval = fb_alloc_cmap(&info->cmap, 256, 0); | 1195 | retval = fb_alloc_cmap(&info->cmap, 256, 0); |
1201 | if (retval < 0) | 1196 | if (retval < 0) |
1202 | goto err_framebuffer_release; | 1197 | goto err_framebuffer_release; |
1203 | 1198 | ||
1204 | if (!fb_find_mode(&info->var, info, mode_option, ps3fb_modedb, | 1199 | if (!fb_find_mode(&info->var, info, mode_option, ps3fb_modedb, |
1205 | ARRAY_SIZE(ps3fb_modedb), | 1200 | ARRAY_SIZE(ps3fb_modedb), |
1206 | ps3fb_vmode(par->new_mode_id), 32)) { | 1201 | ps3fb_vmode(par->new_mode_id), 32)) { |
1207 | retval = -EINVAL; | 1202 | retval = -EINVAL; |
1208 | goto err_fb_dealloc; | 1203 | goto err_fb_dealloc; |
1209 | } | 1204 | } |
1210 | 1205 | ||
1211 | fb_videomode_to_modelist(ps3fb_modedb, ARRAY_SIZE(ps3fb_modedb), | 1206 | fb_videomode_to_modelist(ps3fb_modedb, ARRAY_SIZE(ps3fb_modedb), |
1212 | &info->modelist); | 1207 | &info->modelist); |
1213 | 1208 | ||
1214 | retval = register_framebuffer(info); | 1209 | retval = register_framebuffer(info); |
1215 | if (retval < 0) | 1210 | if (retval < 0) |
1216 | goto err_fb_dealloc; | 1211 | goto err_fb_dealloc; |
1217 | 1212 | ||
1218 | dev->core.driver_data = info; | 1213 | dev->core.driver_data = info; |
1219 | 1214 | ||
1220 | dev_info(info->device, "%s %s, using %u KiB of video memory\n", | 1215 | dev_info(info->device, "%s %s, using %u KiB of video memory\n", |
1221 | dev_driver_string(info->dev), info->dev->bus_id, | 1216 | dev_driver_string(info->dev), info->dev->bus_id, |
1222 | info->fix.smem_len >> 10); | 1217 | info->fix.smem_len >> 10); |
1223 | 1218 | ||
1224 | task = kthread_run(ps3fbd, info, DEVICE_NAME); | 1219 | task = kthread_run(ps3fbd, info, DEVICE_NAME); |
1225 | if (IS_ERR(task)) { | 1220 | if (IS_ERR(task)) { |
1226 | retval = PTR_ERR(task); | 1221 | retval = PTR_ERR(task); |
1227 | goto err_unregister_framebuffer; | 1222 | goto err_unregister_framebuffer; |
1228 | } | 1223 | } |
1229 | 1224 | ||
1230 | ps3fb.task = task; | 1225 | ps3fb.task = task; |
1231 | ps3av_register_flip_ctl(ps3fb_flip_ctl, &ps3fb); | ||
1232 | 1226 | ||
1233 | return 0; | 1227 | return 0; |
1234 | 1228 | ||
1235 | err_unregister_framebuffer: | 1229 | err_unregister_framebuffer: |
1236 | unregister_framebuffer(info); | 1230 | unregister_framebuffer(info); |
1237 | err_fb_dealloc: | 1231 | err_fb_dealloc: |
1238 | fb_dealloc_cmap(&info->cmap); | 1232 | fb_dealloc_cmap(&info->cmap); |
1239 | err_framebuffer_release: | 1233 | err_framebuffer_release: |
1240 | framebuffer_release(info); | 1234 | framebuffer_release(info); |
1241 | err_free_irq: | 1235 | err_free_irq: |
1242 | free_irq(ps3fb.irq_no, &dev->core); | 1236 | free_irq(ps3fb.irq_no, &dev->core); |
1243 | ps3_irq_plug_destroy(ps3fb.irq_no); | 1237 | ps3_irq_plug_destroy(ps3fb.irq_no); |
1244 | err_iounmap_dinfo: | 1238 | err_iounmap_dinfo: |
1245 | iounmap((u8 __force __iomem *)ps3fb.dinfo); | 1239 | iounmap((u8 __force __iomem *)ps3fb.dinfo); |
1246 | err_gpu_context_free: | 1240 | err_gpu_context_free: |
1247 | lv1_gpu_context_free(ps3fb.context_handle); | 1241 | lv1_gpu_context_free(ps3fb.context_handle); |
1248 | err_gpu_memory_free: | 1242 | err_gpu_memory_free: |
1249 | lv1_gpu_memory_free(ps3fb.memory_handle); | 1243 | lv1_gpu_memory_free(ps3fb.memory_handle); |
1250 | err: | 1244 | err: |
1251 | return retval; | 1245 | return retval; |
1252 | } | 1246 | } |
1253 | 1247 | ||
1254 | static int ps3fb_shutdown(struct ps3_system_bus_device *dev) | 1248 | static int ps3fb_shutdown(struct ps3_system_bus_device *dev) |
1255 | { | 1249 | { |
1256 | int status; | 1250 | int status; |
1257 | struct fb_info *info = dev->core.driver_data; | 1251 | struct fb_info *info = dev->core.driver_data; |
1258 | 1252 | ||
1259 | dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__); | 1253 | dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__); |
1260 | 1254 | ||
1261 | ps3fb_flip_ctl(0, &ps3fb); /* flip off */ | 1255 | atomic_inc(&ps3fb.ext_flip); /* flip off */ |
1262 | ps3fb.dinfo->irq.mask = 0; | 1256 | ps3fb.dinfo->irq.mask = 0; |
1263 | 1257 | ||
1264 | ps3av_register_flip_ctl(NULL, NULL); | ||
1265 | if (ps3fb.task) { | 1258 | if (ps3fb.task) { |
1266 | struct task_struct *task = ps3fb.task; | 1259 | struct task_struct *task = ps3fb.task; |
1267 | ps3fb.task = NULL; | 1260 | ps3fb.task = NULL; |
1268 | kthread_stop(task); | 1261 | kthread_stop(task); |
1269 | } | 1262 | } |
1270 | if (ps3fb.irq_no) { | 1263 | if (ps3fb.irq_no) { |
1271 | free_irq(ps3fb.irq_no, &dev->core); | 1264 | free_irq(ps3fb.irq_no, &dev->core); |
1272 | ps3_irq_plug_destroy(ps3fb.irq_no); | 1265 | ps3_irq_plug_destroy(ps3fb.irq_no); |
1273 | } | 1266 | } |
1274 | if (info) { | 1267 | if (info) { |
1275 | unregister_framebuffer(info); | 1268 | unregister_framebuffer(info); |
1276 | fb_dealloc_cmap(&info->cmap); | 1269 | fb_dealloc_cmap(&info->cmap); |
1277 | framebuffer_release(info); | 1270 | framebuffer_release(info); |
1278 | info = dev->core.driver_data = NULL; | 1271 | info = dev->core.driver_data = NULL; |
1279 | } | 1272 | } |
1280 | iounmap((u8 __force __iomem *)ps3fb.dinfo); | 1273 | iounmap((u8 __force __iomem *)ps3fb.dinfo); |
1281 | 1274 | ||
1282 | status = lv1_gpu_context_free(ps3fb.context_handle); | 1275 | status = lv1_gpu_context_free(ps3fb.context_handle); |
1283 | if (status) | 1276 | if (status) |
1284 | dev_dbg(&dev->core, "lv1_gpu_context_free failed: %d\n", | 1277 | dev_dbg(&dev->core, "lv1_gpu_context_free failed: %d\n", |
1285 | status); | 1278 | status); |
1286 | 1279 | ||
1287 | status = lv1_gpu_memory_free(ps3fb.memory_handle); | 1280 | status = lv1_gpu_memory_free(ps3fb.memory_handle); |
1288 | if (status) | 1281 | if (status) |
1289 | dev_dbg(&dev->core, "lv1_gpu_memory_free failed: %d\n", | 1282 | dev_dbg(&dev->core, "lv1_gpu_memory_free failed: %d\n", |
1290 | status); | 1283 | status); |
1291 | 1284 | ||
1292 | ps3_close_hv_device(dev); | 1285 | ps3_close_hv_device(dev); |
1293 | dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__); | 1286 | dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__); |
1294 | 1287 | ||
1295 | return 0; | 1288 | return 0; |
1296 | } | 1289 | } |
1297 | 1290 | ||
1298 | static struct ps3_system_bus_driver ps3fb_driver = { | 1291 | static struct ps3_system_bus_driver ps3fb_driver = { |
1299 | .match_id = PS3_MATCH_ID_GRAPHICS, | 1292 | .match_id = PS3_MATCH_ID_GRAPHICS, |
1300 | .match_sub_id = PS3_MATCH_SUB_ID_FB, | 1293 | .match_sub_id = PS3_MATCH_SUB_ID_FB, |
1301 | .core.name = DEVICE_NAME, | 1294 | .core.name = DEVICE_NAME, |
1302 | .core.owner = THIS_MODULE, | 1295 | .core.owner = THIS_MODULE, |
1303 | .probe = ps3fb_probe, | 1296 | .probe = ps3fb_probe, |
1304 | .remove = ps3fb_shutdown, | 1297 | .remove = ps3fb_shutdown, |
1305 | .shutdown = ps3fb_shutdown, | 1298 | .shutdown = ps3fb_shutdown, |
1306 | }; | 1299 | }; |
1307 | 1300 | ||
1308 | static int __init ps3fb_setup(void) | 1301 | static int __init ps3fb_setup(void) |
1309 | { | 1302 | { |
1310 | char *options; | 1303 | char *options; |
1311 | 1304 | ||
1312 | #ifdef MODULE | 1305 | #ifdef MODULE |
1313 | return 0; | 1306 | return 0; |
1314 | #endif | 1307 | #endif |
1315 | 1308 | ||
1316 | if (fb_get_options(DEVICE_NAME, &options)) | 1309 | if (fb_get_options(DEVICE_NAME, &options)) |
1317 | return -ENXIO; | 1310 | return -ENXIO; |
1318 | 1311 | ||
1319 | if (!options || !*options) | 1312 | if (!options || !*options) |
1320 | return 0; | 1313 | return 0; |
1321 | 1314 | ||
1322 | while (1) { | 1315 | while (1) { |
1323 | char *this_opt = strsep(&options, ","); | 1316 | char *this_opt = strsep(&options, ","); |
1324 | 1317 | ||
1325 | if (!this_opt) | 1318 | if (!this_opt) |
1326 | break; | 1319 | break; |
1327 | if (!*this_opt) | 1320 | if (!*this_opt) |
1328 | continue; | 1321 | continue; |
1329 | if (!strncmp(this_opt, "mode:", 5)) | 1322 | if (!strncmp(this_opt, "mode:", 5)) |
1330 | ps3fb_mode = simple_strtoul(this_opt + 5, NULL, 0); | 1323 | ps3fb_mode = simple_strtoul(this_opt + 5, NULL, 0); |
1331 | else | 1324 | else |
1332 | mode_option = this_opt; | 1325 | mode_option = this_opt; |
1333 | } | 1326 | } |
1334 | return 0; | 1327 | return 0; |
1335 | } | 1328 | } |
1336 | 1329 | ||
1337 | static int __init ps3fb_init(void) | 1330 | static int __init ps3fb_init(void) |
1338 | { | 1331 | { |
1339 | if (!ps3fb_videomemory.address || ps3fb_setup()) | 1332 | if (!ps3fb_videomemory.address || ps3fb_setup()) |
1340 | return -ENXIO; | 1333 | return -ENXIO; |
1341 | 1334 | ||
1342 | return ps3_system_bus_driver_register(&ps3fb_driver); | 1335 | return ps3_system_bus_driver_register(&ps3fb_driver); |
1343 | } | 1336 | } |
1344 | 1337 | ||
1345 | static void __exit ps3fb_exit(void) | 1338 | static void __exit ps3fb_exit(void) |
1346 | { | 1339 | { |
1347 | pr_debug(" -> %s:%d\n", __func__, __LINE__); | 1340 | pr_debug(" -> %s:%d\n", __func__, __LINE__); |
1348 | ps3_system_bus_driver_unregister(&ps3fb_driver); | 1341 | ps3_system_bus_driver_unregister(&ps3fb_driver); |
1349 | pr_debug(" <- %s:%d\n", __func__, __LINE__); | 1342 | pr_debug(" <- %s:%d\n", __func__, __LINE__); |
1350 | } | 1343 | } |
1351 | 1344 | ||
1352 | module_init(ps3fb_init); | 1345 | module_init(ps3fb_init); |
1353 | module_exit(ps3fb_exit); | 1346 | module_exit(ps3fb_exit); |
1354 | 1347 | ||
1355 | MODULE_LICENSE("GPL"); | 1348 | MODULE_LICENSE("GPL"); |