diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2013-03-06 10:15:08 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2013-03-21 06:40:05 -0400 |
commit | 018b0c6f8acb5819591f3b43b51fc342af548c82 (patch) | |
tree | a5831567bc09f0117c2aca5a32dc4043a16d5921 | |
parent | 7333839505d568e0e69a6d02a3ee0f455b6c37a5 (diff) |
[media] siano: make load firmware logic to work with newer firmwares
There are new firmwares for sms2xxx devices. Change the firmware
load logic to handle those newer firmwares and devices.
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r-- | drivers/media/common/siano/smscoreapi.c | 348 | ||||
-rw-r--r-- | drivers/media/common/siano/smscoreapi.h | 8 |
2 files changed, 220 insertions, 136 deletions
diff --git a/drivers/media/common/siano/smscoreapi.c b/drivers/media/common/siano/smscoreapi.c index 7b5d81a30cdf..d489701c3842 100644 --- a/drivers/media/common/siano/smscoreapi.c +++ b/drivers/media/common/siano/smscoreapi.c | |||
@@ -683,6 +683,7 @@ int smscore_register_device(struct smsdevice_params_t *params, | |||
683 | /* init completion events */ | 683 | /* init completion events */ |
684 | init_completion(&dev->version_ex_done); | 684 | init_completion(&dev->version_ex_done); |
685 | init_completion(&dev->data_download_done); | 685 | init_completion(&dev->data_download_done); |
686 | init_completion(&dev->data_validity_done); | ||
686 | init_completion(&dev->trigger_done); | 687 | init_completion(&dev->trigger_done); |
687 | init_completion(&dev->init_device_done); | 688 | init_completion(&dev->init_device_done); |
688 | init_completion(&dev->reload_start_done); | 689 | init_completion(&dev->reload_start_done); |
@@ -753,7 +754,13 @@ EXPORT_SYMBOL_GPL(smscore_register_device); | |||
753 | 754 | ||
754 | static int smscore_sendrequest_and_wait(struct smscore_device_t *coredev, | 755 | static int smscore_sendrequest_and_wait(struct smscore_device_t *coredev, |
755 | void *buffer, size_t size, struct completion *completion) { | 756 | void *buffer, size_t size, struct completion *completion) { |
756 | int rc = coredev->sendrequest_handler(coredev->context, buffer, size); | 757 | int rc; |
758 | |||
759 | if (completion == NULL) | ||
760 | return -EINVAL; | ||
761 | init_completion(completion); | ||
762 | |||
763 | rc = coredev->sendrequest_handler(coredev->context, buffer, size); | ||
757 | if (rc < 0) { | 764 | if (rc < 0) { |
758 | sms_info("sendrequest returned error %d", rc); | 765 | sms_info("sendrequest returned error %d", rc); |
759 | return rc; | 766 | return rc; |
@@ -850,8 +857,9 @@ static int smscore_load_firmware_family2(struct smscore_device_t *coredev, | |||
850 | void *buffer, size_t size) | 857 | void *buffer, size_t size) |
851 | { | 858 | { |
852 | struct SmsFirmware_ST *firmware = (struct SmsFirmware_ST *) buffer; | 859 | struct SmsFirmware_ST *firmware = (struct SmsFirmware_ST *) buffer; |
853 | struct SmsMsgHdr_ST *msg; | 860 | struct SmsMsgData_ST4 *msg; |
854 | u32 mem_address; | 861 | u32 mem_address, calc_checksum = 0; |
862 | u32 i, *ptr; | ||
855 | u8 *payload = firmware->Payload; | 863 | u8 *payload = firmware->Payload; |
856 | int rc = 0; | 864 | int rc = 0; |
857 | firmware->StartAddress = le32_to_cpu(firmware->StartAddress); | 865 | firmware->StartAddress = le32_to_cpu(firmware->StartAddress); |
@@ -874,34 +882,35 @@ static int smscore_load_firmware_family2(struct smscore_device_t *coredev, | |||
874 | 882 | ||
875 | if (coredev->mode != DEVICE_MODE_NONE) { | 883 | if (coredev->mode != DEVICE_MODE_NONE) { |
876 | sms_debug("sending reload command."); | 884 | sms_debug("sending reload command."); |
877 | SMS_INIT_MSG(msg, MSG_SW_RELOAD_START_REQ, | 885 | SMS_INIT_MSG(&msg->xMsgHeader, MSG_SW_RELOAD_START_REQ, |
878 | sizeof(struct SmsMsgHdr_ST)); | 886 | sizeof(struct SmsMsgHdr_ST)); |
879 | rc = smscore_sendrequest_and_wait(coredev, msg, | 887 | rc = smscore_sendrequest_and_wait(coredev, msg, |
880 | msg->msgLength, | 888 | msg->xMsgHeader.msgLength, |
881 | &coredev->reload_start_done); | 889 | &coredev->reload_start_done); |
890 | if (rc < 0) { | ||
891 | sms_err("device reload failed, rc %d", rc); | ||
892 | goto exit_fw_download; | ||
893 | } | ||
882 | mem_address = *(u32 *) &payload[20]; | 894 | mem_address = *(u32 *) &payload[20]; |
883 | } | 895 | } |
884 | 896 | ||
897 | for (i = 0, ptr = (u32 *)firmware->Payload; i < firmware->Length/4 ; | ||
898 | i++, ptr++) | ||
899 | calc_checksum += *ptr; | ||
900 | |||
885 | while (size && rc >= 0) { | 901 | while (size && rc >= 0) { |
886 | struct SmsDataDownload_ST *DataMsg = | 902 | struct SmsDataDownload_ST *DataMsg = |
887 | (struct SmsDataDownload_ST *) msg; | 903 | (struct SmsDataDownload_ST *) msg; |
888 | int payload_size = min((int) size, SMS_MAX_PAYLOAD_SIZE); | 904 | int payload_size = min((int) size, SMS_MAX_PAYLOAD_SIZE); |
889 | 905 | ||
890 | SMS_INIT_MSG(msg, MSG_SMS_DATA_DOWNLOAD_REQ, | 906 | SMS_INIT_MSG(&msg->xMsgHeader, MSG_SMS_DATA_DOWNLOAD_REQ, |
891 | (u16)(sizeof(struct SmsMsgHdr_ST) + | 907 | (u16)(sizeof(struct SmsMsgHdr_ST) + |
892 | sizeof(u32) + payload_size)); | 908 | sizeof(u32) + payload_size)); |
893 | 909 | ||
894 | DataMsg->MemAddr = mem_address; | 910 | DataMsg->MemAddr = mem_address; |
895 | memcpy(DataMsg->Payload, payload, payload_size); | 911 | memcpy(DataMsg->Payload, payload, payload_size); |
896 | 912 | ||
897 | if ((coredev->device_flags & SMS_ROM_NO_RESPONSE) && | 913 | rc = smscore_sendrequest_and_wait(coredev, DataMsg, |
898 | (coredev->mode == DEVICE_MODE_NONE)) | ||
899 | rc = coredev->sendrequest_handler( | ||
900 | coredev->context, DataMsg, | ||
901 | DataMsg->xMsgHeader.msgLength); | ||
902 | else | ||
903 | rc = smscore_sendrequest_and_wait( | ||
904 | coredev, DataMsg, | ||
905 | DataMsg->xMsgHeader.msgLength, | 914 | DataMsg->xMsgHeader.msgLength, |
906 | &coredev->data_download_done); | 915 | &coredev->data_download_done); |
907 | 916 | ||
@@ -910,44 +919,65 @@ static int smscore_load_firmware_family2(struct smscore_device_t *coredev, | |||
910 | mem_address += payload_size; | 919 | mem_address += payload_size; |
911 | } | 920 | } |
912 | 921 | ||
913 | if (rc >= 0) { | 922 | if (rc < 0) |
914 | if (coredev->mode == DEVICE_MODE_NONE) { | 923 | goto exit_fw_download; |
915 | struct SmsMsgData_ST *TriggerMsg = | 924 | |
916 | (struct SmsMsgData_ST *) msg; | 925 | sms_err("sending MSG_SMS_DATA_VALIDITY_REQ expecting 0x%x", |
917 | 926 | calc_checksum); | |
918 | SMS_INIT_MSG(msg, MSG_SMS_SWDOWNLOAD_TRIGGER_REQ, | 927 | SMS_INIT_MSG(&msg->xMsgHeader, MSG_SMS_DATA_VALIDITY_REQ, |
919 | sizeof(struct SmsMsgHdr_ST) + | 928 | sizeof(msg->xMsgHeader) + |
920 | sizeof(u32) * 5); | 929 | sizeof(u32) * 3); |
921 | 930 | msg->msgData[0] = firmware->StartAddress; | |
922 | TriggerMsg->msgData[0] = firmware->StartAddress; | 931 | /* Entry point */ |
923 | /* Entry point */ | 932 | msg->msgData[1] = firmware->Length; |
924 | TriggerMsg->msgData[1] = 5; /* Priority */ | 933 | msg->msgData[2] = 0; /* Regular checksum*/ |
925 | TriggerMsg->msgData[2] = 0x200; /* Stack size */ | 934 | smsendian_handle_tx_message(msg); |
926 | TriggerMsg->msgData[3] = 0; /* Parameter */ | 935 | rc = smscore_sendrequest_and_wait(coredev, msg, |
927 | TriggerMsg->msgData[4] = 4; /* Task ID */ | 936 | msg->xMsgHeader.msgLength, |
928 | 937 | &coredev->data_validity_done); | |
929 | if (coredev->device_flags & SMS_ROM_NO_RESPONSE) { | 938 | if (rc < 0) |
930 | rc = coredev->sendrequest_handler( | 939 | goto exit_fw_download; |
931 | coredev->context, TriggerMsg, | 940 | |
932 | TriggerMsg->xMsgHeader.msgLength); | 941 | if (coredev->mode == DEVICE_MODE_NONE) { |
933 | msleep(100); | 942 | struct SmsMsgData_ST *TriggerMsg = |
934 | } else | 943 | (struct SmsMsgData_ST *) msg; |
935 | rc = smscore_sendrequest_and_wait( | 944 | |
936 | coredev, TriggerMsg, | 945 | sms_debug("sending MSG_SMS_SWDOWNLOAD_TRIGGER_REQ"); |
946 | SMS_INIT_MSG(&msg->xMsgHeader, | ||
947 | MSG_SMS_SWDOWNLOAD_TRIGGER_REQ, | ||
948 | sizeof(struct SmsMsgHdr_ST) + | ||
949 | sizeof(u32) * 5); | ||
950 | |||
951 | TriggerMsg->msgData[0] = firmware->StartAddress; | ||
952 | /* Entry point */ | ||
953 | TriggerMsg->msgData[1] = 6; /* Priority */ | ||
954 | TriggerMsg->msgData[2] = 0x200; /* Stack size */ | ||
955 | TriggerMsg->msgData[3] = 0; /* Parameter */ | ||
956 | TriggerMsg->msgData[4] = 4; /* Task ID */ | ||
957 | |||
958 | smsendian_handle_tx_message((struct SmsMsgHdr_S *)msg); | ||
959 | rc = smscore_sendrequest_and_wait(coredev, TriggerMsg, | ||
937 | TriggerMsg->xMsgHeader.msgLength, | 960 | TriggerMsg->xMsgHeader.msgLength, |
938 | &coredev->trigger_done); | 961 | &coredev->trigger_done); |
939 | } else { | 962 | } else { |
940 | SMS_INIT_MSG(msg, MSG_SW_RELOAD_EXEC_REQ, | 963 | SMS_INIT_MSG(&msg->xMsgHeader, MSG_SW_RELOAD_EXEC_REQ, |
941 | sizeof(struct SmsMsgHdr_ST)); | 964 | sizeof(struct SmsMsgHdr_ST)); |
942 | 965 | smsendian_handle_tx_message((struct SmsMsgHdr_S *)msg); | |
943 | rc = coredev->sendrequest_handler(coredev->context, | 966 | rc = coredev->sendrequest_handler(coredev->context, msg, |
944 | msg, msg->msgLength); | 967 | msg->xMsgHeader.msgLength); |
945 | } | ||
946 | msleep(500); | ||
947 | } | 968 | } |
948 | 969 | ||
949 | sms_debug("rc=%d, postload=%p ", rc, | 970 | if (rc < 0) |
950 | coredev->postload_handler); | 971 | goto exit_fw_download; |
972 | |||
973 | /* | ||
974 | * backward compatibility - wait to device_ready_done for | ||
975 | * not more than 400 ms | ||
976 | */ | ||
977 | msleep(400); | ||
978 | |||
979 | exit_fw_download: | ||
980 | sms_debug("rc=%d, postload=0x%p ", rc, coredev->postload_handler); | ||
951 | 981 | ||
952 | kfree(msg); | 982 | kfree(msg); |
953 | 983 | ||
@@ -956,6 +986,10 @@ static int smscore_load_firmware_family2(struct smscore_device_t *coredev, | |||
956 | rc; | 986 | rc; |
957 | } | 987 | } |
958 | 988 | ||
989 | |||
990 | static char *smscore_get_fw_filename(struct smscore_device_t *coredev, | ||
991 | int mode, int lookup); | ||
992 | |||
959 | /** | 993 | /** |
960 | * loads specified firmware into a buffer and calls device loadfirmware_handler | 994 | * loads specified firmware into a buffer and calls device loadfirmware_handler |
961 | * | 995 | * |
@@ -967,41 +1001,43 @@ static int smscore_load_firmware_family2(struct smscore_device_t *coredev, | |||
967 | * @return 0 on success, <0 on error. | 1001 | * @return 0 on success, <0 on error. |
968 | */ | 1002 | */ |
969 | static int smscore_load_firmware_from_file(struct smscore_device_t *coredev, | 1003 | static int smscore_load_firmware_from_file(struct smscore_device_t *coredev, |
970 | char *filename, | 1004 | int mode, int lookup, |
971 | loadfirmware_t loadfirmware_handler) | 1005 | loadfirmware_t loadfirmware_handler) |
972 | { | 1006 | { |
973 | int rc = -ENOENT; | 1007 | int rc = -ENOENT; |
1008 | u8 *fw_buf; | ||
1009 | u32 fw_buf_size; | ||
974 | const struct firmware *fw; | 1010 | const struct firmware *fw; |
975 | u8 *fw_buffer; | ||
976 | 1011 | ||
977 | if (loadfirmware_handler == NULL && !(coredev->device_flags & | 1012 | char *fw_filename = smscore_get_fw_filename(coredev, mode, lookup); |
978 | SMS_DEVICE_FAMILY2)) | 1013 | if (!strcmp(fw_filename, "none")) |
1014 | return -ENOENT; | ||
1015 | |||
1016 | if (loadfirmware_handler == NULL && !(coredev->device_flags | ||
1017 | & SMS_DEVICE_FAMILY2)) | ||
979 | return -EINVAL; | 1018 | return -EINVAL; |
980 | 1019 | ||
981 | rc = request_firmware(&fw, filename, coredev->device); | 1020 | rc = request_firmware(&fw, fw_filename, coredev->device); |
982 | if (rc < 0) { | 1021 | if (rc < 0) { |
983 | sms_info("failed to open \"%s\"", filename); | 1022 | sms_info("failed to open \"%s\"", fw_filename); |
984 | return rc; | 1023 | return rc; |
985 | } | 1024 | } |
986 | sms_info("read FW %s, size=%zd", filename, fw->size); | 1025 | sms_info("read fw %s, buffer size=0x%zx", fw_filename, fw->size); |
987 | fw_buffer = kmalloc(ALIGN(fw->size, SMS_ALLOC_ALIGNMENT), | 1026 | fw_buf = kmalloc(ALIGN(fw->size, SMS_ALLOC_ALIGNMENT), |
988 | GFP_KERNEL | GFP_DMA); | 1027 | GFP_KERNEL | GFP_DMA); |
989 | if (fw_buffer) { | 1028 | if (!fw_buf) { |
990 | memcpy(fw_buffer, fw->data, fw->size); | ||
991 | |||
992 | rc = (coredev->device_flags & SMS_DEVICE_FAMILY2) ? | ||
993 | smscore_load_firmware_family2(coredev, | ||
994 | fw_buffer, | ||
995 | fw->size) : | ||
996 | loadfirmware_handler(coredev->context, | ||
997 | fw_buffer, fw->size); | ||
998 | |||
999 | kfree(fw_buffer); | ||
1000 | } else { | ||
1001 | sms_info("failed to allocate firmware buffer"); | 1029 | sms_info("failed to allocate firmware buffer"); |
1002 | rc = -ENOMEM; | 1030 | return -ENOMEM; |
1003 | } | 1031 | } |
1032 | memcpy(fw_buf, fw->data, fw->size); | ||
1033 | fw_buf_size = fw->size; | ||
1034 | |||
1035 | rc = (coredev->device_flags & SMS_DEVICE_FAMILY2) ? | ||
1036 | smscore_load_firmware_family2(coredev, fw_buf, fw_buf_size) | ||
1037 | : loadfirmware_handler(coredev->context, fw_buf, | ||
1038 | fw_buf_size); | ||
1004 | 1039 | ||
1040 | kfree(fw_buf); | ||
1005 | release_firmware(fw); | 1041 | release_firmware(fw); |
1006 | 1042 | ||
1007 | return rc; | 1043 | return rc; |
@@ -1050,7 +1086,9 @@ void smscore_unregister_device(struct smscore_device_t *coredev) | |||
1050 | 1086 | ||
1051 | sms_info("waiting for %d buffer(s)", | 1087 | sms_info("waiting for %d buffer(s)", |
1052 | coredev->num_buffers - num_buffers); | 1088 | coredev->num_buffers - num_buffers); |
1089 | kmutex_unlock(&g_smscore_deviceslock); | ||
1053 | msleep(100); | 1090 | msleep(100); |
1091 | kmutex_lock(&g_smscore_deviceslock); | ||
1054 | } | 1092 | } |
1055 | 1093 | ||
1056 | sms_info("freed %d buffers", num_buffers); | 1094 | sms_info("freed %d buffers", num_buffers); |
@@ -1107,30 +1145,73 @@ static int smscore_detect_mode(struct smscore_device_t *coredev) | |||
1107 | } | 1145 | } |
1108 | 1146 | ||
1109 | static char *smscore_fw_lkup[][SMS_NUM_OF_DEVICE_TYPES] = { | 1147 | static char *smscore_fw_lkup[][SMS_NUM_OF_DEVICE_TYPES] = { |
1110 | /*Stellar NOVA A0 Nova B0 VEGA*/ | 1148 | /*Stellar, NOVA A0, Nova B0, VEGA, VENICE, MING, PELE, RIO, DENVER_1530, DENVER_2160 */ |
1111 | /*DVBT*/ | 1149 | /*DVBT*/ |
1112 | {"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"}, | 1150 | { "none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none", "none", "none", "none", "dvb_rio.inp", "none", "none" }, |
1113 | /*DVBH*/ | 1151 | /*DVBH*/ |
1114 | {"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"}, | 1152 | { "none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none", "none", "none", "none", "dvbh_rio.inp", "none", "none" }, |
1115 | /*TDMB*/ | 1153 | /*TDMB*/ |
1116 | {"none", "tdmb_nova_12mhz.inp", "tdmb_nova_12mhz_b0.inp", "none"}, | 1154 | { "none", "tdmb_nova_12mhz.inp", "tdmb_nova_12mhz_b0.inp", "none", "none", "none", "none", "none", "none", "tdmb_denver.inp" }, |
1117 | /*DABIP*/ | 1155 | /*DABIP*/ |
1118 | {"none", "none", "none", "none"}, | 1156 | { "none", "none", "none", "none", "none", "none", "none", "none", "none", "none" }, |
1119 | /*BDA*/ | 1157 | /*DVBT_BDA*/ |
1120 | {"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"}, | 1158 | { "none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none", "none", "none", "none", "dvb_rio.inp", "none", "none" }, |
1121 | /*ISDBT*/ | 1159 | /*ISDBT*/ |
1122 | {"none", "isdbt_nova_12mhz.inp", "isdbt_nova_12mhz_b0.inp", "none"}, | 1160 | { "none", "isdbt_nova_12mhz.inp", "isdbt_nova_12mhz_b0.inp", "none", "none", "none", "isdbt_pele.inp", "isdbt_rio.inp", "none", "none" }, |
1123 | /*ISDBTBDA*/ | 1161 | /*ISDBT_BDA*/ |
1124 | {"none", "isdbt_nova_12mhz.inp", "isdbt_nova_12mhz_b0.inp", "none"}, | 1162 | { "none", "isdbt_nova_12mhz.inp", "isdbt_nova_12mhz_b0.inp", "none", "none", "none", "isdbt_pele.inp", "isdbt_rio.inp", "none", "none" }, |
1125 | /*CMMB*/ | 1163 | /*CMMB*/ |
1126 | {"none", "none", "none", "cmmb_vega_12mhz.inp"} | 1164 | { "none", "none", "none", "cmmb_vega_12mhz.inp", "cmmb_venice_12mhz.inp", "cmmb_ming_app.inp", "none", "none", "none", "none" }, |
1165 | /*RAW - not supported*/ | ||
1166 | { "none", "none", "none", "none", "none", "none", "none", "none", "none", "none" }, | ||
1167 | /*FM*/ | ||
1168 | { "none", "none", "fm_radio.inp", "none", "none", "none", "none", "fm_radio_rio.inp", "none", "none" }, | ||
1169 | /*FM_BDA*/ | ||
1170 | { "none", "none", "fm_radio.inp", "none", "none", "none", "none", "fm_radio_rio.inp", "none", "none" }, | ||
1171 | /*ATSC*/ | ||
1172 | { "none", "none", "none", "none", "none", "none", "none", "none", "atsc_denver.inp", "none" } | ||
1127 | }; | 1173 | }; |
1128 | 1174 | ||
1129 | static inline char *sms_get_fw_name(struct smscore_device_t *coredev, | 1175 | /** |
1130 | int mode, enum sms_device_type_st type) | 1176 | * get firmware file name from one of the two mechanisms : sms_boards or |
1177 | * smscore_fw_lkup. | ||
1178 | * @param coredev pointer to a coredev object returned by | ||
1179 | * smscore_register_device | ||
1180 | * @param mode requested mode of operation | ||
1181 | * @param lookup if 1, always get the fw filename from smscore_fw_lkup | ||
1182 | * table. if 0, try first to get from sms_boards | ||
1183 | * | ||
1184 | * @return 0 on success, <0 on error. | ||
1185 | */ | ||
1186 | static char *smscore_get_fw_filename(struct smscore_device_t *coredev, | ||
1187 | int mode, int lookup) | ||
1131 | { | 1188 | { |
1132 | char **fw = sms_get_board(smscore_get_board_id(coredev))->fw; | 1189 | char **fw; |
1133 | return (fw && fw[mode]) ? fw[mode] : smscore_fw_lkup[mode][type]; | 1190 | int board_id = smscore_get_board_id(coredev); |
1191 | enum sms_device_type_st type = smscore_registry_gettype(coredev->devpath); | ||
1192 | |||
1193 | if ((board_id == SMS_BOARD_UNKNOWN) || (lookup == 1)) { | ||
1194 | sms_debug("trying to get fw name from lookup table mode %d type %d", | ||
1195 | mode, type); | ||
1196 | return smscore_fw_lkup[mode][type]; | ||
1197 | } | ||
1198 | |||
1199 | sms_debug("trying to get fw name from sms_boards board_id %d mode %d", | ||
1200 | board_id, mode); | ||
1201 | fw = sms_get_board(board_id)->fw; | ||
1202 | if (fw == NULL) { | ||
1203 | sms_debug("cannot find fw name in sms_boards, getting from lookup table mode %d type %d", | ||
1204 | mode, type); | ||
1205 | return smscore_fw_lkup[mode][type]; | ||
1206 | } | ||
1207 | |||
1208 | if (fw[mode] == NULL) { | ||
1209 | sms_debug("cannot find fw name in sms_boards, getting from lookup table mode %d type %d", | ||
1210 | mode, type); | ||
1211 | return smscore_fw_lkup[mode][type]; | ||
1212 | } | ||
1213 | |||
1214 | return fw[mode]; | ||
1134 | } | 1215 | } |
1135 | 1216 | ||
1136 | /** | 1217 | /** |
@@ -1145,9 +1226,7 @@ static inline char *sms_get_fw_name(struct smscore_device_t *coredev, | |||
1145 | */ | 1226 | */ |
1146 | int smscore_set_device_mode(struct smscore_device_t *coredev, int mode) | 1227 | int smscore_set_device_mode(struct smscore_device_t *coredev, int mode) |
1147 | { | 1228 | { |
1148 | void *buffer; | ||
1149 | int rc = 0; | 1229 | int rc = 0; |
1150 | enum sms_device_type_st type; | ||
1151 | 1230 | ||
1152 | sms_debug("set device mode to %d", mode); | 1231 | sms_debug("set device mode to %d", mode); |
1153 | if (coredev->device_flags & SMS_DEVICE_FAMILY2) { | 1232 | if (coredev->device_flags & SMS_DEVICE_FAMILY2) { |
@@ -1172,55 +1251,30 @@ int smscore_set_device_mode(struct smscore_device_t *coredev, int mode) | |||
1172 | } | 1251 | } |
1173 | 1252 | ||
1174 | if (!(coredev->modes_supported & (1 << mode))) { | 1253 | if (!(coredev->modes_supported & (1 << mode))) { |
1175 | char *fw_filename; | ||
1176 | |||
1177 | type = smscore_registry_gettype(coredev->devpath); | ||
1178 | fw_filename = sms_get_fw_name(coredev, mode, type); | ||
1179 | |||
1180 | rc = smscore_load_firmware_from_file(coredev, | 1254 | rc = smscore_load_firmware_from_file(coredev, |
1181 | fw_filename, NULL); | 1255 | mode, 0, NULL); |
1182 | if (rc < 0) { | ||
1183 | sms_warn("error %d loading firmware: %s, " | ||
1184 | "trying again with default firmware", | ||
1185 | rc, fw_filename); | ||
1186 | 1256 | ||
1187 | /* try again with the default firmware */ | 1257 | /* |
1188 | fw_filename = smscore_fw_lkup[mode][type]; | 1258 | * try again with the default firmware - |
1259 | * get the fw filename from look-up table | ||
1260 | */ | ||
1261 | if (rc < 0) { | ||
1262 | sms_debug("error %d loading firmware, trying again with default firmware", | ||
1263 | rc); | ||
1189 | rc = smscore_load_firmware_from_file(coredev, | 1264 | rc = smscore_load_firmware_from_file(coredev, |
1190 | fw_filename, NULL); | 1265 | mode, 1, |
1191 | 1266 | NULL); | |
1192 | if (rc < 0) { | 1267 | if (rc < 0) { |
1193 | sms_warn("error %d loading " | 1268 | sms_debug("error %d loading firmware", |
1194 | "firmware: %s", rc, | 1269 | rc); |
1195 | fw_filename); | ||
1196 | return rc; | 1270 | return rc; |
1197 | } | 1271 | } |
1198 | } | 1272 | } |
1199 | sms_log("firmware download success: %s", fw_filename); | 1273 | if (rc >= 0) |
1200 | } else | 1274 | sms_info("firmware download success"); |
1201 | sms_info("mode %d supported by running " | ||
1202 | "firmware", mode); | ||
1203 | |||
1204 | buffer = kmalloc(sizeof(struct SmsMsgData_ST) + | ||
1205 | SMS_DMA_ALIGNMENT, GFP_KERNEL | GFP_DMA); | ||
1206 | if (buffer) { | ||
1207 | struct SmsMsgData_ST *msg = | ||
1208 | (struct SmsMsgData_ST *) | ||
1209 | SMS_ALIGN_ADDRESS(buffer); | ||
1210 | |||
1211 | SMS_INIT_MSG(&msg->xMsgHeader, MSG_SMS_INIT_DEVICE_REQ, | ||
1212 | sizeof(struct SmsMsgData_ST)); | ||
1213 | msg->msgData[0] = mode; | ||
1214 | |||
1215 | rc = smscore_sendrequest_and_wait( | ||
1216 | coredev, msg, msg->xMsgHeader.msgLength, | ||
1217 | &coredev->init_device_done); | ||
1218 | |||
1219 | kfree(buffer); | ||
1220 | } else { | 1275 | } else { |
1221 | sms_err("Could not allocate buffer for " | 1276 | sms_info("mode %d is already supported by running firmware", |
1222 | "init device message."); | 1277 | mode); |
1223 | rc = -ENOMEM; | ||
1224 | } | 1278 | } |
1225 | } else { | 1279 | } else { |
1226 | if (mode < DEVICE_MODE_DVBT || mode > DEVICE_MODE_DVBT_BDA) { | 1280 | if (mode < DEVICE_MODE_DVBT || mode > DEVICE_MODE_DVBT_BDA) { |
@@ -1239,8 +1293,25 @@ int smscore_set_device_mode(struct smscore_device_t *coredev, int mode) | |||
1239 | } | 1293 | } |
1240 | 1294 | ||
1241 | if (rc >= 0) { | 1295 | if (rc >= 0) { |
1296 | char *buffer; | ||
1242 | coredev->mode = mode; | 1297 | coredev->mode = mode; |
1243 | coredev->device_flags &= ~SMS_DEVICE_NOT_READY; | 1298 | coredev->device_flags &= ~SMS_DEVICE_NOT_READY; |
1299 | |||
1300 | buffer = kmalloc(sizeof(struct SmsMsgData_ST) + | ||
1301 | SMS_DMA_ALIGNMENT, GFP_KERNEL | GFP_DMA); | ||
1302 | if (buffer) { | ||
1303 | struct SmsMsgData_ST *msg = (struct SmsMsgData_ST *) SMS_ALIGN_ADDRESS(buffer); | ||
1304 | |||
1305 | SMS_INIT_MSG(&msg->xMsgHeader, MSG_SMS_INIT_DEVICE_REQ, | ||
1306 | sizeof(struct SmsMsgData_ST)); | ||
1307 | msg->msgData[0] = mode; | ||
1308 | |||
1309 | rc = smscore_sendrequest_and_wait( | ||
1310 | coredev, msg, msg->xMsgHeader.msgLength, | ||
1311 | &coredev->init_device_done); | ||
1312 | |||
1313 | kfree(buffer); | ||
1314 | } | ||
1244 | } | 1315 | } |
1245 | 1316 | ||
1246 | if (rc < 0) | 1317 | if (rc < 0) |
@@ -1371,6 +1442,15 @@ void smscore_onresponse(struct smscore_device_t *coredev, | |||
1371 | case MSG_SW_RELOAD_START_RES: | 1442 | case MSG_SW_RELOAD_START_RES: |
1372 | complete(&coredev->reload_start_done); | 1443 | complete(&coredev->reload_start_done); |
1373 | break; | 1444 | break; |
1445 | case MSG_SMS_DATA_VALIDITY_RES: | ||
1446 | { | ||
1447 | struct SmsMsgData_ST *validity = (struct SmsMsgData_ST *) phdr; | ||
1448 | |||
1449 | sms_err("MSG_SMS_DATA_VALIDITY_RES, checksum = 0x%x", | ||
1450 | validity->msgData[0]); | ||
1451 | complete(&coredev->data_validity_done); | ||
1452 | break; | ||
1453 | } | ||
1374 | case MSG_SMS_DATA_DOWNLOAD_RES: | 1454 | case MSG_SMS_DATA_DOWNLOAD_RES: |
1375 | complete(&coredev->data_download_done); | 1455 | complete(&coredev->data_download_done); |
1376 | break; | 1456 | break; |
diff --git a/drivers/media/common/siano/smscoreapi.h b/drivers/media/common/siano/smscoreapi.h index f1440a55cb4d..91db8536c2b0 100644 --- a/drivers/media/common/siano/smscoreapi.h +++ b/drivers/media/common/siano/smscoreapi.h | |||
@@ -162,6 +162,7 @@ struct smscore_device_t { | |||
162 | 162 | ||
163 | /* host <--> device messages */ | 163 | /* host <--> device messages */ |
164 | struct completion version_ex_done, data_download_done, trigger_done; | 164 | struct completion version_ex_done, data_download_done, trigger_done; |
165 | struct completion data_validity_done, device_ready_done; | ||
165 | struct completion init_device_done, reload_start_done, resume_done; | 166 | struct completion init_device_done, reload_start_done, resume_done; |
166 | struct completion gpio_configuration_done, gpio_set_level_done; | 167 | struct completion gpio_configuration_done, gpio_set_level_done; |
167 | struct completion gpio_get_level_done, ir_init_done; | 168 | struct completion gpio_get_level_done, ir_init_done; |
@@ -594,6 +595,11 @@ struct SmsMsgData_ST2 { | |||
594 | u32 msgData[2]; | 595 | u32 msgData[2]; |
595 | }; | 596 | }; |
596 | 597 | ||
598 | struct SmsMsgData_ST4 { | ||
599 | struct SmsMsgHdr_ST xMsgHeader; | ||
600 | u32 msgData[4]; | ||
601 | }; | ||
602 | |||
597 | struct SmsDataDownload_ST { | 603 | struct SmsDataDownload_ST { |
598 | struct SmsMsgHdr_ST xMsgHeader; | 604 | struct SmsMsgHdr_ST xMsgHeader; |
599 | u32 MemAddr; | 605 | u32 MemAddr; |
@@ -998,8 +1004,6 @@ extern void smscore_onresponse(struct smscore_device_t *coredev, | |||
998 | extern int smscore_get_common_buffer_size(struct smscore_device_t *coredev); | 1004 | extern int smscore_get_common_buffer_size(struct smscore_device_t *coredev); |
999 | extern int smscore_map_common_buffer(struct smscore_device_t *coredev, | 1005 | extern int smscore_map_common_buffer(struct smscore_device_t *coredev, |
1000 | struct vm_area_struct *vma); | 1006 | struct vm_area_struct *vma); |
1001 | extern int smscore_get_fw_filename(struct smscore_device_t *coredev, | ||
1002 | int mode, char *filename); | ||
1003 | extern int smscore_send_fw_file(struct smscore_device_t *coredev, | 1007 | extern int smscore_send_fw_file(struct smscore_device_t *coredev, |
1004 | u8 *ufwbuf, int size); | 1008 | u8 *ufwbuf, int size); |
1005 | 1009 | ||