.. | .. |
---|
1 | 1 | // SPDX-License-Identifier: GPL-2.0 |
---|
2 | 2 | |
---|
| 3 | +#include <linux/delay.h> |
---|
3 | 4 | #include <linux/firmware.h> |
---|
4 | | -#include <drm/drmP.h> |
---|
| 5 | +#include <linux/module.h> |
---|
| 6 | + |
---|
5 | 7 | #include "ast_drv.h" |
---|
| 8 | + |
---|
6 | 9 | MODULE_FIRMWARE("ast_dp501_fw.bin"); |
---|
| 10 | + |
---|
| 11 | +static void ast_release_firmware(void *data) |
---|
| 12 | +{ |
---|
| 13 | + struct ast_private *ast = data; |
---|
| 14 | + |
---|
| 15 | + release_firmware(ast->dp501_fw); |
---|
| 16 | + ast->dp501_fw = NULL; |
---|
| 17 | +} |
---|
7 | 18 | |
---|
8 | 19 | static int ast_load_dp501_microcode(struct drm_device *dev) |
---|
9 | 20 | { |
---|
10 | | - struct ast_private *ast = dev->dev_private; |
---|
| 21 | + struct ast_private *ast = to_ast_private(dev); |
---|
| 22 | + int ret; |
---|
11 | 23 | |
---|
12 | | - return request_firmware(&ast->dp501_fw, "ast_dp501_fw.bin", dev->dev); |
---|
| 24 | + ret = request_firmware(&ast->dp501_fw, "ast_dp501_fw.bin", dev->dev); |
---|
| 25 | + if (ret) |
---|
| 26 | + return ret; |
---|
| 27 | + |
---|
| 28 | + return devm_add_action_or_reset(dev->dev, ast_release_firmware, ast); |
---|
13 | 29 | } |
---|
14 | 30 | |
---|
15 | 31 | static void send_ack(struct ast_private *ast) |
---|
.. | .. |
---|
90 | 106 | |
---|
91 | 107 | static bool ast_write_cmd(struct drm_device *dev, u8 data) |
---|
92 | 108 | { |
---|
93 | | - struct ast_private *ast = dev->dev_private; |
---|
| 109 | + struct ast_private *ast = to_ast_private(dev); |
---|
94 | 110 | int retry = 0; |
---|
95 | 111 | if (wait_nack(ast)) { |
---|
96 | 112 | send_nack(ast); |
---|
.. | .. |
---|
112 | 128 | |
---|
113 | 129 | static bool ast_write_data(struct drm_device *dev, u8 data) |
---|
114 | 130 | { |
---|
115 | | - struct ast_private *ast = dev->dev_private; |
---|
| 131 | + struct ast_private *ast = to_ast_private(dev); |
---|
116 | 132 | |
---|
117 | 133 | if (wait_nack(ast)) { |
---|
118 | 134 | send_nack(ast); |
---|
.. | .. |
---|
130 | 146 | #if 0 |
---|
131 | 147 | static bool ast_read_data(struct drm_device *dev, u8 *data) |
---|
132 | 148 | { |
---|
133 | | - struct ast_private *ast = dev->dev_private; |
---|
| 149 | + struct ast_private *ast = to_ast_private(dev); |
---|
134 | 150 | u8 tmp; |
---|
135 | 151 | |
---|
136 | 152 | *data = 0; |
---|
.. | .. |
---|
169 | 185 | |
---|
170 | 186 | bool ast_backup_fw(struct drm_device *dev, u8 *addr, u32 size) |
---|
171 | 187 | { |
---|
172 | | - struct ast_private *ast = dev->dev_private; |
---|
| 188 | + struct ast_private *ast = to_ast_private(dev); |
---|
173 | 189 | u32 i, data; |
---|
174 | 190 | u32 boot_address; |
---|
| 191 | + |
---|
| 192 | + if (ast->config_mode != ast_use_p2a) |
---|
| 193 | + return false; |
---|
175 | 194 | |
---|
176 | 195 | data = ast_mindwm(ast, 0x1e6e2100) & 0x01; |
---|
177 | 196 | if (data) { |
---|
.. | .. |
---|
185 | 204 | |
---|
186 | 205 | static bool ast_launch_m68k(struct drm_device *dev) |
---|
187 | 206 | { |
---|
188 | | - struct ast_private *ast = dev->dev_private; |
---|
| 207 | + struct ast_private *ast = to_ast_private(dev); |
---|
189 | 208 | u32 i, data, len = 0; |
---|
190 | 209 | u32 boot_address; |
---|
191 | 210 | u8 *fw_addr = NULL; |
---|
192 | 211 | u8 jreg; |
---|
| 212 | + |
---|
| 213 | + if (ast->config_mode != ast_use_p2a) |
---|
| 214 | + return false; |
---|
193 | 215 | |
---|
194 | 216 | data = ast_mindwm(ast, 0x1e6e2100) & 0x01; |
---|
195 | 217 | if (!data) { |
---|
.. | .. |
---|
252 | 274 | |
---|
253 | 275 | u8 ast_get_dp501_max_clk(struct drm_device *dev) |
---|
254 | 276 | { |
---|
255 | | - struct ast_private *ast = dev->dev_private; |
---|
| 277 | + struct ast_private *ast = to_ast_private(dev); |
---|
256 | 278 | u32 boot_address, offset, data; |
---|
257 | 279 | u8 linkcap[4], linkrate, linklanes, maxclk = 0xff; |
---|
| 280 | + u32 *plinkcap; |
---|
258 | 281 | |
---|
259 | | - boot_address = get_fw_base(ast); |
---|
| 282 | + if (ast->config_mode == ast_use_p2a) { |
---|
| 283 | + boot_address = get_fw_base(ast); |
---|
260 | 284 | |
---|
261 | | - /* validate FW version */ |
---|
262 | | - offset = 0xf000; |
---|
263 | | - data = ast_mindwm(ast, boot_address + offset); |
---|
264 | | - if ((data & 0xf0) != 0x10) /* version: 1x */ |
---|
265 | | - return maxclk; |
---|
| 285 | + /* validate FW version */ |
---|
| 286 | + offset = AST_DP501_GBL_VERSION; |
---|
| 287 | + data = ast_mindwm(ast, boot_address + offset); |
---|
| 288 | + if ((data & AST_DP501_FW_VERSION_MASK) != AST_DP501_FW_VERSION_1) /* version: 1x */ |
---|
| 289 | + return maxclk; |
---|
266 | 290 | |
---|
267 | | - /* Read Link Capability */ |
---|
268 | | - offset = 0xf014; |
---|
269 | | - *(u32 *)linkcap = ast_mindwm(ast, boot_address + offset); |
---|
270 | | - if (linkcap[2] == 0) { |
---|
271 | | - linkrate = linkcap[0]; |
---|
272 | | - linklanes = linkcap[1]; |
---|
273 | | - data = (linkrate == 0x0a) ? (90 * linklanes) : (54 * linklanes); |
---|
274 | | - if (data > 0xff) |
---|
275 | | - data = 0xff; |
---|
276 | | - maxclk = (u8)data; |
---|
| 291 | + /* Read Link Capability */ |
---|
| 292 | + offset = AST_DP501_LINKRATE; |
---|
| 293 | + plinkcap = (u32 *)linkcap; |
---|
| 294 | + *plinkcap = ast_mindwm(ast, boot_address + offset); |
---|
| 295 | + if (linkcap[2] == 0) { |
---|
| 296 | + linkrate = linkcap[0]; |
---|
| 297 | + linklanes = linkcap[1]; |
---|
| 298 | + data = (linkrate == 0x0a) ? (90 * linklanes) : (54 * linklanes); |
---|
| 299 | + if (data > 0xff) |
---|
| 300 | + data = 0xff; |
---|
| 301 | + maxclk = (u8)data; |
---|
| 302 | + } |
---|
| 303 | + } else { |
---|
| 304 | + if (!ast->dp501_fw_buf) |
---|
| 305 | + return AST_DP501_DEFAULT_DCLK; /* 1024x768 as default */ |
---|
| 306 | + |
---|
| 307 | + /* dummy read */ |
---|
| 308 | + offset = 0x0000; |
---|
| 309 | + data = readl(ast->dp501_fw_buf + offset); |
---|
| 310 | + |
---|
| 311 | + /* validate FW version */ |
---|
| 312 | + offset = AST_DP501_GBL_VERSION; |
---|
| 313 | + data = readl(ast->dp501_fw_buf + offset); |
---|
| 314 | + if ((data & AST_DP501_FW_VERSION_MASK) != AST_DP501_FW_VERSION_1) /* version: 1x */ |
---|
| 315 | + return maxclk; |
---|
| 316 | + |
---|
| 317 | + /* Read Link Capability */ |
---|
| 318 | + offset = AST_DP501_LINKRATE; |
---|
| 319 | + plinkcap = (u32 *)linkcap; |
---|
| 320 | + *plinkcap = readl(ast->dp501_fw_buf + offset); |
---|
| 321 | + if (linkcap[2] == 0) { |
---|
| 322 | + linkrate = linkcap[0]; |
---|
| 323 | + linklanes = linkcap[1]; |
---|
| 324 | + data = (linkrate == 0x0a) ? (90 * linklanes) : (54 * linklanes); |
---|
| 325 | + if (data > 0xff) |
---|
| 326 | + data = 0xff; |
---|
| 327 | + maxclk = (u8)data; |
---|
| 328 | + } |
---|
277 | 329 | } |
---|
278 | 330 | return maxclk; |
---|
279 | 331 | } |
---|
280 | 332 | |
---|
281 | 333 | bool ast_dp501_read_edid(struct drm_device *dev, u8 *ediddata) |
---|
282 | 334 | { |
---|
283 | | - struct ast_private *ast = dev->dev_private; |
---|
| 335 | + struct ast_private *ast = to_ast_private(dev); |
---|
284 | 336 | u32 i, boot_address, offset, data; |
---|
| 337 | + u32 *pEDIDidx; |
---|
285 | 338 | |
---|
286 | | - boot_address = get_fw_base(ast); |
---|
| 339 | + if (ast->config_mode == ast_use_p2a) { |
---|
| 340 | + boot_address = get_fw_base(ast); |
---|
287 | 341 | |
---|
288 | | - /* validate FW version */ |
---|
289 | | - offset = 0xf000; |
---|
290 | | - data = ast_mindwm(ast, boot_address + offset); |
---|
291 | | - if ((data & 0xf0) != 0x10) |
---|
292 | | - return false; |
---|
| 342 | + /* validate FW version */ |
---|
| 343 | + offset = AST_DP501_GBL_VERSION; |
---|
| 344 | + data = ast_mindwm(ast, boot_address + offset); |
---|
| 345 | + if ((data & AST_DP501_FW_VERSION_MASK) != AST_DP501_FW_VERSION_1) |
---|
| 346 | + return false; |
---|
293 | 347 | |
---|
294 | | - /* validate PnP Monitor */ |
---|
295 | | - offset = 0xf010; |
---|
296 | | - data = ast_mindwm(ast, boot_address + offset); |
---|
297 | | - if (!(data & 0x01)) |
---|
298 | | - return false; |
---|
| 348 | + /* validate PnP Monitor */ |
---|
| 349 | + offset = AST_DP501_PNPMONITOR; |
---|
| 350 | + data = ast_mindwm(ast, boot_address + offset); |
---|
| 351 | + if (!(data & AST_DP501_PNP_CONNECTED)) |
---|
| 352 | + return false; |
---|
299 | 353 | |
---|
300 | | - /* Read EDID */ |
---|
301 | | - offset = 0xf020; |
---|
302 | | - for (i = 0; i < 128; i += 4) { |
---|
303 | | - data = ast_mindwm(ast, boot_address + offset + i); |
---|
304 | | - *(u32 *)(ediddata + i) = data; |
---|
| 354 | + /* Read EDID */ |
---|
| 355 | + offset = AST_DP501_EDID_DATA; |
---|
| 356 | + for (i = 0; i < 128; i += 4) { |
---|
| 357 | + data = ast_mindwm(ast, boot_address + offset + i); |
---|
| 358 | + pEDIDidx = (u32 *)(ediddata + i); |
---|
| 359 | + *pEDIDidx = data; |
---|
| 360 | + } |
---|
| 361 | + } else { |
---|
| 362 | + if (!ast->dp501_fw_buf) |
---|
| 363 | + return false; |
---|
| 364 | + |
---|
| 365 | + /* dummy read */ |
---|
| 366 | + offset = 0x0000; |
---|
| 367 | + data = readl(ast->dp501_fw_buf + offset); |
---|
| 368 | + |
---|
| 369 | + /* validate FW version */ |
---|
| 370 | + offset = AST_DP501_GBL_VERSION; |
---|
| 371 | + data = readl(ast->dp501_fw_buf + offset); |
---|
| 372 | + if ((data & AST_DP501_FW_VERSION_MASK) != AST_DP501_FW_VERSION_1) |
---|
| 373 | + return false; |
---|
| 374 | + |
---|
| 375 | + /* validate PnP Monitor */ |
---|
| 376 | + offset = AST_DP501_PNPMONITOR; |
---|
| 377 | + data = readl(ast->dp501_fw_buf + offset); |
---|
| 378 | + if (!(data & AST_DP501_PNP_CONNECTED)) |
---|
| 379 | + return false; |
---|
| 380 | + |
---|
| 381 | + /* Read EDID */ |
---|
| 382 | + offset = AST_DP501_EDID_DATA; |
---|
| 383 | + for (i = 0; i < 128; i += 4) { |
---|
| 384 | + data = readl(ast->dp501_fw_buf + offset + i); |
---|
| 385 | + pEDIDidx = (u32 *)(ediddata + i); |
---|
| 386 | + *pEDIDidx = data; |
---|
| 387 | + } |
---|
305 | 388 | } |
---|
306 | 389 | |
---|
307 | 390 | return true; |
---|
.. | .. |
---|
309 | 392 | |
---|
310 | 393 | static bool ast_init_dvo(struct drm_device *dev) |
---|
311 | 394 | { |
---|
312 | | - struct ast_private *ast = dev->dev_private; |
---|
| 395 | + struct ast_private *ast = to_ast_private(dev); |
---|
313 | 396 | u8 jreg; |
---|
314 | 397 | u32 data; |
---|
315 | 398 | ast_write32(ast, 0xf004, 0x1e6e0000); |
---|
.. | .. |
---|
382 | 465 | |
---|
383 | 466 | static void ast_init_analog(struct drm_device *dev) |
---|
384 | 467 | { |
---|
385 | | - struct ast_private *ast = dev->dev_private; |
---|
| 468 | + struct ast_private *ast = to_ast_private(dev); |
---|
386 | 469 | u32 data; |
---|
387 | 470 | |
---|
388 | 471 | /* |
---|
.. | .. |
---|
409 | 492 | |
---|
410 | 493 | void ast_init_3rdtx(struct drm_device *dev) |
---|
411 | 494 | { |
---|
412 | | - struct ast_private *ast = dev->dev_private; |
---|
| 495 | + struct ast_private *ast = to_ast_private(dev); |
---|
413 | 496 | u8 jreg; |
---|
414 | 497 | |
---|
415 | 498 | if (ast->chip == AST2300 || ast->chip == AST2400) { |
---|
.. | .. |
---|
431 | 514 | ast_init_analog(dev); |
---|
432 | 515 | } |
---|
433 | 516 | } |
---|
434 | | -} |
---|
435 | | - |
---|
436 | | -void ast_release_firmware(struct drm_device *dev) |
---|
437 | | -{ |
---|
438 | | - struct ast_private *ast = dev->dev_private; |
---|
439 | | - |
---|
440 | | - release_firmware(ast->dp501_fw); |
---|
441 | | - ast->dp501_fw = NULL; |
---|
442 | 517 | } |
---|