aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVincent Abriou <vincent.abriou@st.com>2015-11-02 04:38:15 -0500
committerVincent Abriou <vincent.abriou@st.com>2015-11-03 07:04:56 -0500
commite00fe64a5ccd94590e1c3325346b60aa0ffdc1ff (patch)
tree794cbba04b04f22a9f562bed19aee86f6f4bdee2
parent738be9d6ca3adccdd92798fd25f94fef0b27e073 (diff)
drm/sti: load HQVDP firmware the first time HQVDP's plane is used
The way to load the HQVDP firmware has been updated. HQVDP firmware is now loaded the first time an HQVDP plane is used and no more when the HQVDP driver is bound. This solves the dependency we had on the file system availability. The first time the HQVDP plane is used, we are sure that file system is available so request_firmware function will match. CONFIG_FW_LOADER_USER_HELPER_FALLBACK is then no more mandatory. Cc: Takashi Iwai <tiwai@suse.de> Signed-off-by: Vincent Abriou <vincent.abriou@st.com>
-rw-r--r--drivers/gpu/drm/sti/Kconfig1
-rw-r--r--drivers/gpu/drm/sti/sti_hqvdp.c302
2 files changed, 150 insertions, 153 deletions
diff --git a/drivers/gpu/drm/sti/Kconfig b/drivers/gpu/drm/sti/Kconfig
index 3f8d590e5c34..10c1b1926e6f 100644
--- a/drivers/gpu/drm/sti/Kconfig
+++ b/drivers/gpu/drm/sti/Kconfig
@@ -7,6 +7,5 @@ config DRM_STI
7 select DRM_KMS_CMA_HELPER 7 select DRM_KMS_CMA_HELPER
8 select DRM_PANEL 8 select DRM_PANEL
9 select FW_LOADER 9 select FW_LOADER
10 select FW_LOADER_USER_HELPER_FALLBACK
11 help 10 help
12 Choose this option to enable DRM on STM stiH41x chipset 11 Choose this option to enable DRM on STM stiH41x chipset
diff --git a/drivers/gpu/drm/sti/sti_hqvdp.c b/drivers/gpu/drm/sti/sti_hqvdp.c
index 348c7c58f385..ea0690bc77d5 100644
--- a/drivers/gpu/drm/sti/sti_hqvdp.c
+++ b/drivers/gpu/drm/sti/sti_hqvdp.c
@@ -628,6 +628,153 @@ static void sti_hqvdp_init(struct sti_hqvdp *hqvdp)
628 memset(hqvdp->hqvdp_cmd, 0, size); 628 memset(hqvdp->hqvdp_cmd, 0, size);
629} 629}
630 630
631static void sti_hqvdp_init_plugs(struct sti_hqvdp *hqvdp)
632{
633 /* Configure Plugs (same for RD & WR) */
634 writel(PLUG_PAGE_SIZE_256, hqvdp->regs + HQVDP_RD_PLUG_PAGE_SIZE);
635 writel(PLUG_MIN_OPC_8, hqvdp->regs + HQVDP_RD_PLUG_MIN_OPC);
636 writel(PLUG_MAX_OPC_64, hqvdp->regs + HQVDP_RD_PLUG_MAX_OPC);
637 writel(PLUG_MAX_CHK_2X, hqvdp->regs + HQVDP_RD_PLUG_MAX_CHK);
638 writel(PLUG_MAX_MSG_1X, hqvdp->regs + HQVDP_RD_PLUG_MAX_MSG);
639 writel(PLUG_MIN_SPACE_1, hqvdp->regs + HQVDP_RD_PLUG_MIN_SPACE);
640 writel(PLUG_CONTROL_ENABLE, hqvdp->regs + HQVDP_RD_PLUG_CONTROL);
641
642 writel(PLUG_PAGE_SIZE_256, hqvdp->regs + HQVDP_WR_PLUG_PAGE_SIZE);
643 writel(PLUG_MIN_OPC_8, hqvdp->regs + HQVDP_WR_PLUG_MIN_OPC);
644 writel(PLUG_MAX_OPC_64, hqvdp->regs + HQVDP_WR_PLUG_MAX_OPC);
645 writel(PLUG_MAX_CHK_2X, hqvdp->regs + HQVDP_WR_PLUG_MAX_CHK);
646 writel(PLUG_MAX_MSG_1X, hqvdp->regs + HQVDP_WR_PLUG_MAX_MSG);
647 writel(PLUG_MIN_SPACE_1, hqvdp->regs + HQVDP_WR_PLUG_MIN_SPACE);
648 writel(PLUG_CONTROL_ENABLE, hqvdp->regs + HQVDP_WR_PLUG_CONTROL);
649}
650
651/**
652 * sti_hqvdp_start_xp70
653 * @hqvdp: hqvdp pointer
654 *
655 * Run the xP70 initialization sequence
656 */
657static void sti_hqvdp_start_xp70(struct sti_hqvdp *hqvdp)
658{
659 const struct firmware *firmware;
660 u32 *fw_rd_plug, *fw_wr_plug, *fw_pmem, *fw_dmem;
661 u8 *data;
662 int i;
663 struct fw_header {
664 int rd_size;
665 int wr_size;
666 int pmem_size;
667 int dmem_size;
668 } *header;
669
670 DRM_DEBUG_DRIVER("\n");
671
672 if (hqvdp->xp70_initialized) {
673 DRM_INFO("HQVDP XP70 already initialized\n");
674 return;
675 }
676
677 /* Request firmware */
678 if (request_firmware(&firmware, HQVDP_FMW_NAME, hqvdp->dev)) {
679 DRM_ERROR("Can't get HQVDP firmware\n");
680 return;
681 }
682
683 /* Check firmware parts */
684 if (!firmware) {
685 DRM_ERROR("Firmware not available\n");
686 return;
687 }
688
689 header = (struct fw_header *)firmware->data;
690 if (firmware->size < sizeof(*header)) {
691 DRM_ERROR("Invalid firmware size (%d)\n", firmware->size);
692 goto out;
693 }
694 if ((sizeof(*header) + header->rd_size + header->wr_size +
695 header->pmem_size + header->dmem_size) != firmware->size) {
696 DRM_ERROR("Invalid fmw structure (%d+%d+%d+%d+%d != %d)\n",
697 sizeof(*header), header->rd_size, header->wr_size,
698 header->pmem_size, header->dmem_size,
699 firmware->size);
700 goto out;
701 }
702
703 data = (u8 *)firmware->data;
704 data += sizeof(*header);
705 fw_rd_plug = (void *)data;
706 data += header->rd_size;
707 fw_wr_plug = (void *)data;
708 data += header->wr_size;
709 fw_pmem = (void *)data;
710 data += header->pmem_size;
711 fw_dmem = (void *)data;
712
713 /* Enable clock */
714 if (clk_prepare_enable(hqvdp->clk))
715 DRM_ERROR("Failed to prepare/enable HQVDP clk\n");
716
717 /* Reset */
718 writel(SW_RESET_CTRL_FULL, hqvdp->regs + HQVDP_MBX_SW_RESET_CTRL);
719
720 for (i = 0; i < POLL_MAX_ATTEMPT; i++) {
721 if (readl(hqvdp->regs + HQVDP_MBX_STARTUP_CTRL1)
722 & STARTUP_CTRL1_RST_DONE)
723 break;
724 msleep(POLL_DELAY_MS);
725 }
726 if (i == POLL_MAX_ATTEMPT) {
727 DRM_ERROR("Could not reset\n");
728 goto out;
729 }
730
731 /* Init Read & Write plugs */
732 for (i = 0; i < header->rd_size / 4; i++)
733 writel(fw_rd_plug[i], hqvdp->regs + HQVDP_RD_PLUG + i * 4);
734 for (i = 0; i < header->wr_size / 4; i++)
735 writel(fw_wr_plug[i], hqvdp->regs + HQVDP_WR_PLUG + i * 4);
736
737 sti_hqvdp_init_plugs(hqvdp);
738
739 /* Authorize Idle Mode */
740 writel(STARTUP_CTRL1_AUTH_IDLE, hqvdp->regs + HQVDP_MBX_STARTUP_CTRL1);
741
742 /* Prevent VTG interruption during the boot */
743 writel(SOFT_VSYNC_SW_CTRL_IRQ, hqvdp->regs + HQVDP_MBX_SOFT_VSYNC);
744 writel(0, hqvdp->regs + HQVDP_MBX_NEXT_CMD);
745
746 /* Download PMEM & DMEM */
747 for (i = 0; i < header->pmem_size / 4; i++)
748 writel(fw_pmem[i], hqvdp->regs + HQVDP_PMEM + i * 4);
749 for (i = 0; i < header->dmem_size / 4; i++)
750 writel(fw_dmem[i], hqvdp->regs + HQVDP_DMEM + i * 4);
751
752 /* Enable fetch */
753 writel(STARTUP_CTRL2_FETCH_EN, hqvdp->regs + HQVDP_MBX_STARTUP_CTRL2);
754
755 /* Wait end of boot */
756 for (i = 0; i < POLL_MAX_ATTEMPT; i++) {
757 if (readl(hqvdp->regs + HQVDP_MBX_INFO_XP70)
758 & INFO_XP70_FW_READY)
759 break;
760 msleep(POLL_DELAY_MS);
761 }
762 if (i == POLL_MAX_ATTEMPT) {
763 DRM_ERROR("Could not boot\n");
764 goto out;
765 }
766
767 /* Launch Vsync */
768 writel(SOFT_VSYNC_HW, hqvdp->regs + HQVDP_MBX_SOFT_VSYNC);
769
770 DRM_INFO("HQVDP XP70 initialized\n");
771
772 hqvdp->xp70_initialized = true;
773
774out:
775 release_firmware(firmware);
776}
777
631static void sti_hqvdp_atomic_update(struct drm_plane *drm_plane, 778static void sti_hqvdp_atomic_update(struct drm_plane *drm_plane,
632 struct drm_plane_state *oldstate) 779 struct drm_plane_state *oldstate)
633{ 780{
@@ -754,6 +901,9 @@ static void sti_hqvdp_atomic_update(struct drm_plane *drm_plane,
754 sti_hqvdp_update_hvsrc(HVSRC_VERT, scale_v, &cmd->hvsrc); 901 sti_hqvdp_update_hvsrc(HVSRC_VERT, scale_v, &cmd->hvsrc);
755 902
756 if (first_prepare) { 903 if (first_prepare) {
904 /* Start HQVDP XP70 coprocessor */
905 sti_hqvdp_start_xp70(hqvdp);
906
757 /* Prevent VTG shutdown */ 907 /* Prevent VTG shutdown */
758 if (clk_prepare_enable(hqvdp->clk_pix_main)) { 908 if (clk_prepare_enable(hqvdp->clk_pix_main)) {
759 DRM_ERROR("Failed to prepare/enable pix main clk\n"); 909 DRM_ERROR("Failed to prepare/enable pix main clk\n");
@@ -836,168 +986,16 @@ static struct drm_plane *sti_hqvdp_create(struct drm_device *drm_dev,
836 return &hqvdp->plane.drm_plane; 986 return &hqvdp->plane.drm_plane;
837} 987}
838 988
839static void sti_hqvdp_init_plugs(struct sti_hqvdp *hqvdp)
840{
841 /* Configure Plugs (same for RD & WR) */
842 writel(PLUG_PAGE_SIZE_256, hqvdp->regs + HQVDP_RD_PLUG_PAGE_SIZE);
843 writel(PLUG_MIN_OPC_8, hqvdp->regs + HQVDP_RD_PLUG_MIN_OPC);
844 writel(PLUG_MAX_OPC_64, hqvdp->regs + HQVDP_RD_PLUG_MAX_OPC);
845 writel(PLUG_MAX_CHK_2X, hqvdp->regs + HQVDP_RD_PLUG_MAX_CHK);
846 writel(PLUG_MAX_MSG_1X, hqvdp->regs + HQVDP_RD_PLUG_MAX_MSG);
847 writel(PLUG_MIN_SPACE_1, hqvdp->regs + HQVDP_RD_PLUG_MIN_SPACE);
848 writel(PLUG_CONTROL_ENABLE, hqvdp->regs + HQVDP_RD_PLUG_CONTROL);
849
850 writel(PLUG_PAGE_SIZE_256, hqvdp->regs + HQVDP_WR_PLUG_PAGE_SIZE);
851 writel(PLUG_MIN_OPC_8, hqvdp->regs + HQVDP_WR_PLUG_MIN_OPC);
852 writel(PLUG_MAX_OPC_64, hqvdp->regs + HQVDP_WR_PLUG_MAX_OPC);
853 writel(PLUG_MAX_CHK_2X, hqvdp->regs + HQVDP_WR_PLUG_MAX_CHK);
854 writel(PLUG_MAX_MSG_1X, hqvdp->regs + HQVDP_WR_PLUG_MAX_MSG);
855 writel(PLUG_MIN_SPACE_1, hqvdp->regs + HQVDP_WR_PLUG_MIN_SPACE);
856 writel(PLUG_CONTROL_ENABLE, hqvdp->regs + HQVDP_WR_PLUG_CONTROL);
857}
858
859/**
860 * sti_hqvdp_start_xp70
861 * @firmware: firmware found
862 * @ctxt: hqvdp structure
863 *
864 * Run the xP70 initialization sequence
865 */
866static void sti_hqvdp_start_xp70(const struct firmware *firmware, void *ctxt)
867{
868 struct sti_hqvdp *hqvdp = ctxt;
869 u32 *fw_rd_plug, *fw_wr_plug, *fw_pmem, *fw_dmem;
870 u8 *data;
871 int i;
872 struct fw_header {
873 int rd_size;
874 int wr_size;
875 int pmem_size;
876 int dmem_size;
877 } *header;
878
879 DRM_DEBUG_DRIVER("\n");
880
881 if (hqvdp->xp70_initialized) {
882 DRM_INFO("HQVDP XP70 already initialized\n");
883 return;
884 }
885
886 /* Check firmware parts */
887 if (!firmware) {
888 DRM_ERROR("Firmware not available\n");
889 return;
890 }
891
892 header = (struct fw_header *) firmware->data;
893 if (firmware->size < sizeof(*header)) {
894 DRM_ERROR("Invalid firmware size (%d)\n", firmware->size);
895 goto out;
896 }
897 if ((sizeof(*header) + header->rd_size + header->wr_size +
898 header->pmem_size + header->dmem_size) != firmware->size) {
899 DRM_ERROR("Invalid fmw structure (%d+%d+%d+%d+%d != %d)\n",
900 sizeof(*header), header->rd_size, header->wr_size,
901 header->pmem_size, header->dmem_size,
902 firmware->size);
903 goto out;
904 }
905
906 data = (u8 *) firmware->data;
907 data += sizeof(*header);
908 fw_rd_plug = (void *) data;
909 data += header->rd_size;
910 fw_wr_plug = (void *) data;
911 data += header->wr_size;
912 fw_pmem = (void *) data;
913 data += header->pmem_size;
914 fw_dmem = (void *) data;
915
916 /* Enable clock */
917 if (clk_prepare_enable(hqvdp->clk))
918 DRM_ERROR("Failed to prepare/enable HQVDP clk\n");
919
920 /* Reset */
921 writel(SW_RESET_CTRL_FULL, hqvdp->regs + HQVDP_MBX_SW_RESET_CTRL);
922
923 for (i = 0; i < POLL_MAX_ATTEMPT; i++) {
924 if (readl(hqvdp->regs + HQVDP_MBX_STARTUP_CTRL1)
925 & STARTUP_CTRL1_RST_DONE)
926 break;
927 msleep(POLL_DELAY_MS);
928 }
929 if (i == POLL_MAX_ATTEMPT) {
930 DRM_ERROR("Could not reset\n");
931 goto out;
932 }
933
934 /* Init Read & Write plugs */
935 for (i = 0; i < header->rd_size / 4; i++)
936 writel(fw_rd_plug[i], hqvdp->regs + HQVDP_RD_PLUG + i * 4);
937 for (i = 0; i < header->wr_size / 4; i++)
938 writel(fw_wr_plug[i], hqvdp->regs + HQVDP_WR_PLUG + i * 4);
939
940 sti_hqvdp_init_plugs(hqvdp);
941
942 /* Authorize Idle Mode */
943 writel(STARTUP_CTRL1_AUTH_IDLE, hqvdp->regs + HQVDP_MBX_STARTUP_CTRL1);
944
945 /* Prevent VTG interruption during the boot */
946 writel(SOFT_VSYNC_SW_CTRL_IRQ, hqvdp->regs + HQVDP_MBX_SOFT_VSYNC);
947 writel(0, hqvdp->regs + HQVDP_MBX_NEXT_CMD);
948
949 /* Download PMEM & DMEM */
950 for (i = 0; i < header->pmem_size / 4; i++)
951 writel(fw_pmem[i], hqvdp->regs + HQVDP_PMEM + i * 4);
952 for (i = 0; i < header->dmem_size / 4; i++)
953 writel(fw_dmem[i], hqvdp->regs + HQVDP_DMEM + i * 4);
954
955 /* Enable fetch */
956 writel(STARTUP_CTRL2_FETCH_EN, hqvdp->regs + HQVDP_MBX_STARTUP_CTRL2);
957
958 /* Wait end of boot */
959 for (i = 0; i < POLL_MAX_ATTEMPT; i++) {
960 if (readl(hqvdp->regs + HQVDP_MBX_INFO_XP70)
961 & INFO_XP70_FW_READY)
962 break;
963 msleep(POLL_DELAY_MS);
964 }
965 if (i == POLL_MAX_ATTEMPT) {
966 DRM_ERROR("Could not boot\n");
967 goto out;
968 }
969
970 /* Launch Vsync */
971 writel(SOFT_VSYNC_HW, hqvdp->regs + HQVDP_MBX_SOFT_VSYNC);
972
973 DRM_INFO("HQVDP XP70 initialized\n");
974
975 hqvdp->xp70_initialized = true;
976
977out:
978 release_firmware(firmware);
979}
980
981int sti_hqvdp_bind(struct device *dev, struct device *master, void *data) 989int sti_hqvdp_bind(struct device *dev, struct device *master, void *data)
982{ 990{
983 struct sti_hqvdp *hqvdp = dev_get_drvdata(dev); 991 struct sti_hqvdp *hqvdp = dev_get_drvdata(dev);
984 struct drm_device *drm_dev = data; 992 struct drm_device *drm_dev = data;
985 struct drm_plane *plane; 993 struct drm_plane *plane;
986 int err;
987 994
988 DRM_DEBUG_DRIVER("\n"); 995 DRM_DEBUG_DRIVER("\n");
989 996
990 hqvdp->drm_dev = drm_dev; 997 hqvdp->drm_dev = drm_dev;
991 998
992 /* Request for firmware */
993 err = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
994 HQVDP_FMW_NAME, hqvdp->dev,
995 GFP_KERNEL, hqvdp, sti_hqvdp_start_xp70);
996 if (err) {
997 DRM_ERROR("Can't get HQVDP firmware\n");
998 return err;
999 }
1000
1001 /* Create HQVDP plane once xp70 is initialized */ 999 /* Create HQVDP plane once xp70 is initialized */
1002 plane = sti_hqvdp_create(drm_dev, hqvdp->dev, STI_HQVDP_0); 1000 plane = sti_hqvdp_create(drm_dev, hqvdp->dev, STI_HQVDP_0);
1003 if (!plane) 1001 if (!plane)