diff options
Diffstat (limited to 'drivers/media/video/pvrusb2/pvrusb2-hdw.c')
-rw-r--r-- | drivers/media/video/pvrusb2/pvrusb2-hdw.c | 150 |
1 files changed, 125 insertions, 25 deletions
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 5d9045268cf5..7172f66a6a28 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c | |||
@@ -2605,7 +2605,85 @@ void pvr2_hdw_trigger_module_log(struct pvr2_hdw *hdw) | |||
2605 | } while (0); LOCK_GIVE(hdw->big_lock); | 2605 | } while (0); LOCK_GIVE(hdw->big_lock); |
2606 | } | 2606 | } |
2607 | 2607 | ||
2608 | void pvr2_hdw_cpufw_set_enabled(struct pvr2_hdw *hdw, int enable_flag) | 2608 | |
2609 | /* Grab EEPROM contents, needed for direct method. */ | ||
2610 | #define EEPROM_SIZE 8192 | ||
2611 | #define trace_eeprom(...) pvr2_trace(PVR2_TRACE_EEPROM,__VA_ARGS__) | ||
2612 | static u8 *pvr2_full_eeprom_fetch(struct pvr2_hdw *hdw) | ||
2613 | { | ||
2614 | struct i2c_msg msg[2]; | ||
2615 | u8 *eeprom; | ||
2616 | u8 iadd[2]; | ||
2617 | u8 addr; | ||
2618 | u16 eepromSize; | ||
2619 | unsigned int offs; | ||
2620 | int ret; | ||
2621 | int mode16 = 0; | ||
2622 | unsigned pcnt,tcnt; | ||
2623 | eeprom = kmalloc(EEPROM_SIZE,GFP_KERNEL); | ||
2624 | if (!eeprom) { | ||
2625 | pvr2_trace(PVR2_TRACE_ERROR_LEGS, | ||
2626 | "Failed to allocate memory" | ||
2627 | " required to read eeprom"); | ||
2628 | return NULL; | ||
2629 | } | ||
2630 | |||
2631 | trace_eeprom("Value for eeprom addr from controller was 0x%x", | ||
2632 | hdw->eeprom_addr); | ||
2633 | addr = hdw->eeprom_addr; | ||
2634 | /* Seems that if the high bit is set, then the *real* eeprom | ||
2635 | address is shifted right now bit position (noticed this in | ||
2636 | newer PVR USB2 hardware) */ | ||
2637 | if (addr & 0x80) addr >>= 1; | ||
2638 | |||
2639 | /* FX2 documentation states that a 16bit-addressed eeprom is | ||
2640 | expected if the I2C address is an odd number (yeah, this is | ||
2641 | strange but it's what they do) */ | ||
2642 | mode16 = (addr & 1); | ||
2643 | eepromSize = (mode16 ? EEPROM_SIZE : 256); | ||
2644 | trace_eeprom("Examining %d byte eeprom at location 0x%x" | ||
2645 | " using %d bit addressing",eepromSize,addr, | ||
2646 | mode16 ? 16 : 8); | ||
2647 | |||
2648 | msg[0].addr = addr; | ||
2649 | msg[0].flags = 0; | ||
2650 | msg[0].len = mode16 ? 2 : 1; | ||
2651 | msg[0].buf = iadd; | ||
2652 | msg[1].addr = addr; | ||
2653 | msg[1].flags = I2C_M_RD; | ||
2654 | |||
2655 | /* We have to do the actual eeprom data fetch ourselves, because | ||
2656 | (1) we're only fetching part of the eeprom, and (2) if we were | ||
2657 | getting the whole thing our I2C driver can't grab it in one | ||
2658 | pass - which is what tveeprom is otherwise going to attempt */ | ||
2659 | memset(eeprom,0,EEPROM_SIZE); | ||
2660 | for (tcnt = 0; tcnt < EEPROM_SIZE; tcnt += pcnt) { | ||
2661 | pcnt = 16; | ||
2662 | if (pcnt + tcnt > EEPROM_SIZE) pcnt = EEPROM_SIZE-tcnt; | ||
2663 | offs = tcnt + (eepromSize - EEPROM_SIZE); | ||
2664 | if (mode16) { | ||
2665 | iadd[0] = offs >> 8; | ||
2666 | iadd[1] = offs; | ||
2667 | } else { | ||
2668 | iadd[0] = offs; | ||
2669 | } | ||
2670 | msg[1].len = pcnt; | ||
2671 | msg[1].buf = eeprom+tcnt; | ||
2672 | if ((ret = i2c_transfer(&hdw->i2c_adap, | ||
2673 | msg,ARRAY_SIZE(msg))) != 2) { | ||
2674 | pvr2_trace(PVR2_TRACE_ERROR_LEGS, | ||
2675 | "eeprom fetch set offs err=%d",ret); | ||
2676 | kfree(eeprom); | ||
2677 | return NULL; | ||
2678 | } | ||
2679 | } | ||
2680 | return eeprom; | ||
2681 | } | ||
2682 | |||
2683 | |||
2684 | void pvr2_hdw_cpufw_set_enabled(struct pvr2_hdw *hdw, | ||
2685 | int prom_flag, | ||
2686 | int enable_flag) | ||
2609 | { | 2687 | { |
2610 | int ret; | 2688 | int ret; |
2611 | u16 address; | 2689 | u16 address; |
@@ -2619,37 +2697,59 @@ void pvr2_hdw_cpufw_set_enabled(struct pvr2_hdw *hdw, int enable_flag) | |||
2619 | kfree(hdw->fw_buffer); | 2697 | kfree(hdw->fw_buffer); |
2620 | hdw->fw_buffer = NULL; | 2698 | hdw->fw_buffer = NULL; |
2621 | hdw->fw_size = 0; | 2699 | hdw->fw_size = 0; |
2622 | /* Now release the CPU. It will disconnect and | 2700 | if (hdw->fw_cpu_flag) { |
2623 | reconnect later. */ | 2701 | /* Now release the CPU. It will disconnect |
2624 | pvr2_hdw_cpureset_assert(hdw,0); | 2702 | and reconnect later. */ |
2703 | pvr2_hdw_cpureset_assert(hdw,0); | ||
2704 | } | ||
2625 | break; | 2705 | break; |
2626 | } | 2706 | } |
2627 | 2707 | ||
2628 | pvr2_trace(PVR2_TRACE_FIRMWARE, | 2708 | hdw->fw_cpu_flag = (prom_flag == 0); |
2629 | "Preparing to suck out CPU firmware"); | 2709 | if (hdw->fw_cpu_flag) { |
2630 | hdw->fw_size = 0x2000; | 2710 | pvr2_trace(PVR2_TRACE_FIRMWARE, |
2631 | hdw->fw_buffer = kzalloc(hdw->fw_size,GFP_KERNEL); | 2711 | "Preparing to suck out CPU firmware"); |
2632 | if (!hdw->fw_buffer) { | 2712 | hdw->fw_size = 0x2000; |
2633 | hdw->fw_size = 0; | 2713 | hdw->fw_buffer = kzalloc(hdw->fw_size,GFP_KERNEL); |
2634 | break; | 2714 | if (!hdw->fw_buffer) { |
2635 | } | 2715 | hdw->fw_size = 0; |
2716 | break; | ||
2717 | } | ||
2636 | 2718 | ||
2637 | /* We have to hold the CPU during firmware upload. */ | 2719 | /* We have to hold the CPU during firmware upload. */ |
2638 | pvr2_hdw_cpureset_assert(hdw,1); | 2720 | pvr2_hdw_cpureset_assert(hdw,1); |
2639 | 2721 | ||
2640 | /* download the firmware from address 0000-1fff in 2048 | 2722 | /* download the firmware from address 0000-1fff in 2048 |
2641 | (=0x800) bytes chunk. */ | 2723 | (=0x800) bytes chunk. */ |
2642 | 2724 | ||
2643 | pvr2_trace(PVR2_TRACE_FIRMWARE,"Grabbing CPU firmware"); | 2725 | pvr2_trace(PVR2_TRACE_FIRMWARE, |
2644 | pipe = usb_rcvctrlpipe(hdw->usb_dev, 0); | 2726 | "Grabbing CPU firmware"); |
2645 | for(address = 0; address < hdw->fw_size; address += 0x800) { | 2727 | pipe = usb_rcvctrlpipe(hdw->usb_dev, 0); |
2646 | ret = usb_control_msg(hdw->usb_dev,pipe,0xa0,0xc0, | 2728 | for(address = 0; address < hdw->fw_size; |
2647 | address,0, | 2729 | address += 0x800) { |
2648 | hdw->fw_buffer+address,0x800,HZ); | 2730 | ret = usb_control_msg(hdw->usb_dev,pipe, |
2649 | if (ret < 0) break; | 2731 | 0xa0,0xc0, |
2650 | } | 2732 | address,0, |
2733 | hdw->fw_buffer+address, | ||
2734 | 0x800,HZ); | ||
2735 | if (ret < 0) break; | ||
2736 | } | ||
2651 | 2737 | ||
2652 | pvr2_trace(PVR2_TRACE_FIRMWARE,"Done grabbing CPU firmware"); | 2738 | pvr2_trace(PVR2_TRACE_FIRMWARE, |
2739 | "Done grabbing CPU firmware"); | ||
2740 | } else { | ||
2741 | pvr2_trace(PVR2_TRACE_FIRMWARE, | ||
2742 | "Sucking down EEPROM contents"); | ||
2743 | hdw->fw_buffer = pvr2_full_eeprom_fetch(hdw); | ||
2744 | if (!hdw->fw_buffer) { | ||
2745 | pvr2_trace(PVR2_TRACE_FIRMWARE, | ||
2746 | "EEPROM content suck failed."); | ||
2747 | break; | ||
2748 | } | ||
2749 | hdw->fw_size = EEPROM_SIZE; | ||
2750 | pvr2_trace(PVR2_TRACE_FIRMWARE, | ||
2751 | "Done sucking down EEPROM contents"); | ||
2752 | } | ||
2653 | 2753 | ||
2654 | } while (0); LOCK_GIVE(hdw->big_lock); | 2754 | } while (0); LOCK_GIVE(hdw->big_lock); |
2655 | } | 2755 | } |