From b252f0d3e203d080029365fe7c7990a849299026 Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Wed, 8 Oct 2014 08:23:34 +0800 Subject: Encoding: Add one hook callback function to detect encoding capabilitiy on Haswell Some Haswell machine doesn't support the encoding. So it should be disabled. Otherwise the driver can't report the supported capability correctly. V2->V3:Based on the Matt Turner's suggestion the __cpuid defined in GCC cpuid.h is called directly, which is helpful to handle the PIC issue on 32-bit. And unsigned data type is updated to uint32_t. V1->V2: Minor update based on comment from Gwenole Beauchesne. For example: use the bool tye and remove the hardcoded value Signed-off-by: Zhao Yakui --- src/i965_device_info.c | 111 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/src/i965_device_info.c b/src/i965_device_info.c index 3abc1370..2d3ced41 100644 --- a/src/i965_device_info.c +++ b/src/i965_device_info.c @@ -27,6 +27,11 @@ #include #include "i965_drv_video.h" +#include +#include +#include +#include + /* Extra set of chroma formats supported for H.264 decoding (beyond YUV 4:2:0) */ #define EXTRA_H264_DEC_CHROMA_FORMATS \ (VA_RT_FORMAT_YUV400) @@ -155,6 +160,8 @@ static struct hw_codec_info ivb_hw_codec_info = { }, }; +static void hsw_hw_codec_preinit(VADriverContextP ctx, struct hw_codec_info *codec_info); + extern struct hw_context *gen75_dec_hw_context_init(VADriverContextP, struct object_config *); extern struct hw_context *gen75_enc_hw_context_init(VADriverContextP, struct object_config *); extern struct hw_context *gen75_proc_context_init(VADriverContextP, struct object_config *); @@ -164,6 +171,7 @@ static struct hw_codec_info hsw_hw_codec_info = { .proc_hw_context_init = gen75_proc_context_init, .render_init = genx_render_init, .post_processing_context_init = i965_post_processing_context_init, + .preinit_hw_codec = hsw_hw_codec_preinit, .max_width = 4096, .max_height = 4096, @@ -418,3 +426,106 @@ i965_get_device_info(int devid) return NULL; } } + +static void cpuid(unsigned int op, + uint32_t *eax, uint32_t *ebx, + uint32_t *ecx, uint32_t *edx) +{ + __cpuid_count(op, 0, *eax, *ebx, *ecx, *edx); +} + +/* + * This function doesn't check the length. And the caller should + * assure that the length of input string should be greater than 48. + */ + +static int intel_driver_detect_cpustring(char *model_id) +{ + uint32_t *rdata; + + if (model_id == NULL) + return -EINVAL; + + rdata = (uint32_t *)model_id; + + /* obtain the max supported extended CPUID info */ + cpuid(0x80000000, &rdata[0], &rdata[1], &rdata[2], &rdata[3]); + + /* If the max extended CPUID info is less than 0x80000004, fail */ + if (rdata[0] < 0x80000004) + return -EINVAL; + + /* obtain the CPUID string */ + cpuid(0x80000002, &rdata[0], &rdata[1], &rdata[2], &rdata[3]); + cpuid(0x80000003, &rdata[4], &rdata[5], &rdata[6], &rdata[7]); + cpuid(0x80000004, &rdata[8], &rdata[9], &rdata[10], &rdata[11]); + + *(model_id + 48) = '\0'; + return 0; +} + +/* + * the hook_list for HSW. + * It is captured by /proc/cpuinfo and the space character is stripped. + */ +const static char *hsw_cpu_hook_list[] = { +"Intel(R)Pentium(R)3556U", +"Intel(R)Pentium(R)3560Y", +"Intel(R)Pentium(R)3550M", +"Intel(R)Celeron(R)2980U", +"Intel(R)Celeron(R)2955U", +"Intel(R)Celeron(R)2950M", +}; + +static void hsw_hw_codec_preinit(VADriverContextP ctx, struct hw_codec_info *codec_info) +{ + char model_string[64]; + char *model_ptr, *tmp_ptr; + int i, model_len, list_len; + bool found; + + memset(model_string, 0, sizeof(model_string)); + + /* If it can't detect cpu model_string, leave it alone */ + if (intel_driver_detect_cpustring(model_string)) + return; + + /* strip the cpufreq info */ + model_ptr = model_string; + tmp_ptr = strstr(model_ptr, "@"); + + if (tmp_ptr) + *tmp_ptr = '\0'; + + /* strip the space character */ + model_ptr = model_string; + model_len = strlen(model_string); + for (i = 0; i < model_len; i++) { + if (model_string[i] != ' ') { + *model_ptr = model_string[i]; + model_ptr++; + } + } + *model_ptr = '\0'; + + found = false; + list_len = sizeof(hsw_cpu_hook_list) / sizeof(char *); + model_len = strlen(model_string); + for (i = 0; i < list_len; i++) { + model_ptr = (char *)hsw_cpu_hook_list[i]; + + if (strlen(model_ptr) != model_len) + continue; + + if (strncasecmp(model_string, model_ptr, model_len) == 0) { + found = true; + break; + } + } + + if (found) { + codec_info->has_h264_encoding = 0; + codec_info->has_h264_mvc_encoding = 0; + codec_info->has_mpeg2_encoding = 0; + } +} -- cgit v1.2.1