static int hdmi_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct resource *res; struct hdmi_device *hdmi_dev = NULL; int ret; dev_info(dev, "probe start\n"); hdmi_dev = devm_kzalloc(&pdev->dev, sizeof(struct hdmi_device), GFP_KERNEL); if (!hdmi_dev) { dev_err(&pdev->dev, "no memory for hdmi device\n"); return -ENOMEM; } hdmi_dev->dev = dev; /* store platform data ptr to mixer context */ of_property_read_u32(dev->of_node, "ip_ver", &hdmi_dev->ip_ver); dev_info(dev, "HDMI ip version %d\n", hdmi_dev->ip_ver); /* mapping HDMI registers */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { dev_err(dev, "get hdmi memory resource failed.\n"); return -ENXIO; } hdmi_dev->regs = devm_request_and_ioremap(&pdev->dev, res); if (hdmi_dev->regs == NULL) { dev_err(dev, "failed to claim register region for hdmi\n"); return -ENOENT; } /* mapping HDMIPHY_APB registers */ res = platform_get_resource(pdev, IORESOURCE_MEM, 1); if (!res) { dev_err(dev, "get hdmiphy memory resource failed.\n"); return -ENXIO; } hdmi_dev->phy_regs = devm_request_and_ioremap(&pdev->dev, res); if (hdmi_dev->phy_regs == NULL) { dev_err(dev, "failed to claim register region for hdmiphy\n"); return -ENOENT; } /* Internal hpd */ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!res) { dev_err(dev, "get internal interrupt resource failed.\n"); return -ENXIO; } ret = devm_request_irq(dev, res->start, hdmi_irq_handler, 0, "hdmi-int", hdmi_dev); if (ret) { dev_err(dev, "request int interrupt failed.\n"); return ret; } else { hdmi_dev->int_irq = res->start; disable_irq(hdmi_dev->int_irq); dev_info(dev, "success request hdmi-int irq\n"); } /* setting v4l2 name to prevent WARN_ON in v4l2_device_register */ strlcpy(hdmi_dev->v4l2_dev.name, dev_name(dev), sizeof(hdmi_dev->v4l2_dev.name)); /* passing NULL owner prevents driver from erasing drvdata */ ret = v4l2_device_register(NULL, &hdmi_dev->v4l2_dev); if (ret) { dev_err(dev, "could not register v4l2 device.\n"); goto fail; } INIT_WORK(&hdmi_dev->hpd_work, hdmi_hpd_work); INIT_DELAYED_WORK(&hdmi_dev->hpd_work_ext, hdmi_hpd_work_ext); /* setting the clocks */ ret = hdmi_resources_init(hdmi_dev); if (ret) goto fail_vdev; /* HDMI pin control */ hdmi_dev->pinctrl = devm_pinctrl_get(dev); if (IS_ERR(hdmi_dev->pinctrl)) { dev_err(dev, "could not set hdmi internal hpd pins\n"); goto fail_clk; } else { hdmi_dev->pin_int = pinctrl_lookup_state(hdmi_dev->pinctrl, "hdmi_hdmi_hpd"); if(IS_ERR(hdmi_dev->pin_int)) { dev_err(dev, "could not get hdmi internal hpd pin state\n"); goto fail_clk; } hdmi_dev->pin_ext = pinctrl_lookup_state(hdmi_dev->pinctrl, "hdmi_ext_hpd"); if(IS_ERR(hdmi_dev->pin_ext)) { dev_err(dev, "could not get hdmi external hpd pin state\n"); goto fail_clk; } } /* setting the GPIO */ ret = hdmi_set_gpio(hdmi_dev); if (ret) { dev_err(dev, "failed to get GPIO\n"); goto fail_clk; } /* register the switch device for HPD */ hdmi_dev->hpd_switch.name = "hdmi"; ret = switch_dev_register(&hdmi_dev->hpd_switch); if (ret) { dev_err(dev, "request switch class failed.\n"); goto fail_gpio; } dev_info(dev, "success register switch device\n"); /* External hpd */ hdmi_dev->ext_irq = gpio_to_irq(hdmi_dev->res.gpio_hpd); ret = devm_request_irq(dev, hdmi_dev->ext_irq, hdmi_irq_handler_ext, IRQ_TYPE_EDGE_BOTH, "hdmi-ext", hdmi_dev); if (ret) { dev_err(dev, "request ext interrupt failed.\n"); goto fail_switch; } else { dev_info(dev, "success request hdmi-ext irq\n"); } #ifdef CONFIG_SEC_MHL_SUPPORT hdmi_dev->audio_ch_switch.name = "ch_hdmi_audio"; ret = switch_dev_register(&hdmi_dev->audio_ch_switch); if (ret) { dev_err(dev, "request hdmi_audio_switch class failed.\n"); goto fail_switch; } #endif mutex_init(&hdmi_dev->mutex); hdmi_dev->cur_timings = hdmi_conf[HDMI_DEFAULT_TIMINGS_IDX].dv_timings; hdmi_dev->cur_conf = hdmi_conf[HDMI_DEFAULT_TIMINGS_IDX].conf; /* default audio configuration : disable audio */ hdmi_dev->audio_enable = 1; hdmi_dev->audio_channel_count = 2; hdmi_dev->sample_rate = DEFAULT_SAMPLE_RATE; hdmi_dev->color_range = HDMI_RGB709_0_255; hdmi_dev->bits_per_sample = DEFAULT_BITS_PER_SAMPLE; hdmi_dev->audio_codec = DEFAULT_AUDIO_CODEC; /* hdmi audio master clock */ ret = hdmi_get_audio_master(hdmi_dev); if (ret) { hdmi_dev->audio_master_clk = 0; dev_warn(dev, "failed to get audio master information\n"); } /* default aspect ratio is 16:9 */ hdmi_dev->aspect = HDMI_ASPECT_RATIO_16_9; /* default HDMI streaming is stoped */ hdmi_dev->streaming = HDMI_STOP; /* register hdmi subdev as entity */ ret = hdmi_register_entity(hdmi_dev); if (ret) goto fail_mutex; hdmi_entity_info_print(hdmi_dev); pm_runtime_enable(dev); /* initialize hdcp resource */ ret = hdcp_prepare(hdmi_dev); if (ret) goto fail_mutex; /* work after booting */ queue_delayed_work(system_nrt_wq, &hdmi_dev->hpd_work_ext, msecs_to_jiffies(1500)); /* mapping SYSTEM registers */ ret = hdmi_get_sysreg_addr(hdmi_dev); if (ret) goto fail_mutex; dev_info(dev, "probe sucessful\n"); hdmi_debugfs_init(hdmi_dev); return 0; fail_mutex: mutex_destroy(&hdmi_dev->mutex); fail_switch: switch_dev_unregister(&hdmi_dev->hpd_switch); fail_gpio: gpio_free(hdmi_dev->res.gpio_hpd); gpio_free(hdmi_dev->res.gpio_ls); gpio_free(hdmi_dev->res.gpio_dcdc); fail_clk: hdmi_resources_cleanup(hdmi_dev); fail_vdev: v4l2_device_unregister(&hdmi_dev->v4l2_dev); fail: dev_err(dev, "probe failed\n"); return ret; }
static int hdmi_probe(struct platform_device *pdev) { struct s5p_hdmi_platdata *pdata = NULL; struct device *dev = &pdev->dev; struct resource *res; struct i2c_adapter *phy_adapter; struct hdmi_device *hdmi_dev = NULL; struct hdmi_driver_data *drv_data; int ret; dev_info(dev, "probe start\n"); hdmi_dev = devm_kzalloc(&pdev->dev, sizeof(struct hdmi_device), GFP_KERNEL); if (!hdmi_dev) { dev_err(&pdev->dev, "no memory for hdmi device\n"); return -ENOMEM; } hdmi_dev->dev = dev; hdmi_dev->pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); if (!hdmi_dev->pdata) { dev_err(&pdev->dev, "no memory for state\n"); return -ENOMEM; } /* store platform data ptr to mixer context */ if (dev->of_node) { of_property_read_u32(dev->of_node, "ip_ver", &hdmi_dev->pdata->ip_ver); pdata = hdmi_dev->pdata; } else { hdmi_dev->pdata = dev->platform_data; pdata = hdmi_dev->pdata; } dev_info(dev, "HDMI ip version %d\n", pdata->ip_ver); /* mapping HDMI registers */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { dev_err(dev, "get hdmi memory resource failed.\n"); return -ENXIO; } hdmi_dev->regs = devm_request_and_ioremap(&pdev->dev, res); if (hdmi_dev->regs == NULL) { dev_err(dev, "failed to claim register region for hdmi\n"); return -ENOENT; } /* mapping HDMIPHY_APB registers */ res = platform_get_resource(pdev, IORESOURCE_MEM, 1); if (!res) { dev_err(dev, "get hdmiphy memory resource failed.\n"); return -ENXIO; } hdmi_dev->phy_regs = devm_request_and_ioremap(&pdev->dev, res); if (hdmi_dev->phy_regs == NULL) { dev_err(dev, "failed to claim register region for hdmiphy\n"); return -ENOENT; } /* Internal hpd */ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!res) { dev_err(dev, "get internal interrupt resource failed.\n"); return -ENXIO; } ret = devm_request_irq(dev, res->start, hdmi_irq_handler, 0, "hdmi-int", hdmi_dev); if (ret) { dev_err(dev, "request int interrupt failed.\n"); return ret; } else { hdmi_dev->int_irq = res->start; disable_irq(hdmi_dev->int_irq); dev_info(dev, "success request hdmi-int irq\n"); } /* setting v4l2 name to prevent WARN_ON in v4l2_device_register */ strlcpy(hdmi_dev->v4l2_dev.name, dev_name(dev), sizeof(hdmi_dev->v4l2_dev.name)); /* passing NULL owner prevents driver from erasing drvdata */ ret = v4l2_device_register(NULL, &hdmi_dev->v4l2_dev); if (ret) { dev_err(dev, "could not register v4l2 device.\n"); goto fail; } INIT_WORK(&hdmi_dev->hpd_work, hdmi_hpd_work); INIT_DELAYED_WORK(&hdmi_dev->hpd_work_ext, hdmi_hpd_work_ext); /* setting the clocks */ ret = hdmi_resources_init(hdmi_dev); if (ret) goto fail_vdev; /* setting the GPIO */ ret = hdmi_set_gpio(hdmi_dev); if (ret) { dev_err(dev, "failed to get GPIO\n"); goto fail_clk; } /* External hpd */ hdmi_dev->ext_irq = gpio_to_irq(hdmi_dev->res.gpio_hpd); ret = devm_request_irq(dev, hdmi_dev->ext_irq, hdmi_irq_handler_ext, IRQ_TYPE_EDGE_BOTH, "hdmi-ext", hdmi_dev); if (ret) { dev_err(dev, "request ext interrupt failed.\n"); goto fail_gpio; } else { dev_info(dev, "success request hdmi-ext irq\n"); } hdmi_dev->hpd_switch.name = "hdmi"; ret = switch_dev_register(&hdmi_dev->hpd_switch); if (ret) { dev_err(dev, "request switch class failed.\n"); goto fail_gpio; } mutex_init(&hdmi_dev->mutex); if (soc_is_exynos5250()) { drv_data = (struct hdmi_driver_data *) platform_get_device_id(pdev)->driver_data; dev_info(dev, "hdmiphy i2c bus number = %d\n", drv_data->hdmiphy_bus); phy_adapter = i2c_get_adapter(drv_data->hdmiphy_bus); if (phy_adapter == NULL) { dev_err(dev, "adapter request failed\n"); ret = -ENXIO; goto fail_switch; } hdmi_dev->phy_sd = v4l2_i2c_new_subdev_board(&hdmi_dev->v4l2_dev, phy_adapter, &hdmiphy_info, NULL); /* on failure or not adapter is no longer useful */ i2c_put_adapter(phy_adapter); if (hdmi_dev->phy_sd == NULL) { dev_err(dev, "missing subdev for hdmiphy\n"); ret = -ENODEV; goto fail_switch; } } hdmi_dev->cur_timings = hdmi_conf[HDMI_DEFAULT_TIMINGS_IDX].dv_timings; /* FIXME: missing fail preset is not supported */ hdmi_dev->cur_conf = hdmi_conf[HDMI_DEFAULT_TIMINGS_IDX].conf; /* default audio configuration : enable audio */ hdmi_dev->audio_enable = 1; hdmi_dev->audio_channel_count = 2; hdmi_dev->sample_rate = DEFAULT_SAMPLE_RATE; hdmi_dev->color_range = HDMI_RGB709_0_255; hdmi_dev->bits_per_sample = DEFAULT_BITS_PER_SAMPLE; hdmi_dev->audio_codec = DEFAULT_AUDIO_CODEC; /* default aspect ratio is 16:9 */ hdmi_dev->aspect = HDMI_ASPECT_RATIO_16_9; /* default HDMI streaming is stoped */ hdmi_dev->streaming = HDMI_STOP; /* register hdmi subdev as entity */ ret = hdmi_register_entity(hdmi_dev); if (ret) goto fail_switch; hdmi_entity_info_print(hdmi_dev); pm_runtime_enable(dev); /* initialize hdcp resource */ ret = hdcp_prepare(hdmi_dev); if (ret) goto fail_switch; /* work after booting */ queue_delayed_work(system_nrt_wq, &hdmi_dev->hpd_work_ext, msecs_to_jiffies(1500)); /* TODO : Check the PHY power off is implemented at pm_domains * If not, PHY power off should be applied at here */ dev_info(dev, "probe sucessful\n"); hdmi_debugfs_init(hdmi_dev); return 0; fail_switch: switch_dev_unregister(&hdmi_dev->hpd_switch); mutex_destroy(&hdmi_dev->mutex); fail_gpio: gpio_free(hdmi_dev->res.gpio_hpd); gpio_free(hdmi_dev->res.gpio_ls); gpio_free(hdmi_dev->res.gpio_dcdc); fail_clk: hdmi_resources_cleanup(hdmi_dev); fail_vdev: v4l2_device_unregister(&hdmi_dev->v4l2_dev); fail: dev_err(dev, "probe failed\n"); return ret; }